diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-19 18:08:11 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-19 18:08:11 +0000 |
commit | d84f18d66c1fc46f244b0f4dec8bf65b90d9882a (patch) | |
tree | 2382ce0df6d7417e93afdf113a9fd15d7b46a653 | |
parent | f2151c65d5826f0609a716e185893787b6375ae3 (diff) | |
download | gitlab-ce-d84f18d66c1fc46f244b0f4dec8bf65b90d9882a.tar.gz |
Add latest changes from gitlab-org/gitlab@master
54 files changed, 751 insertions, 260 deletions
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue index 447d7bf21a5..35165c9b481 100644 --- a/app/assets/javascripts/issue_show/components/fields/description.vue +++ b/app/assets/javascripts/issue_show/components/fields/description.vue @@ -45,22 +45,24 @@ export default { :markdown-docs-path="markdownDocsPath" :can-attach-file="canAttachFile" :enable-autocomplete="enableAutocomplete" + :textarea-value="formState.description" > - <textarea - id="issue-description" - ref="textarea" - slot="textarea" - v-model="formState.description" - class="note-textarea js-gfm-input js-autosize markdown-area - qa-description-textarea" - dir="auto" - data-supports-quick-actions="false" - :aria-label="__('Description')" - :placeholder="__('Write a comment or drag your files here…')" - @keydown.meta.enter="updateIssuable" - @keydown.ctrl.enter="updateIssuable" - > - </textarea> + <template #textarea> + <textarea + id="issue-description" + ref="textarea" + v-model="formState.description" + class="note-textarea js-gfm-input js-autosize markdown-area + qa-description-textarea" + dir="auto" + data-supports-quick-actions="false" + :aria-label="__('Description')" + :placeholder="__('Write a comment or drag your files here…')" + @keydown.meta.enter="updateIssuable" + @keydown.ctrl.enter="updateIssuable" + > + </textarea> + </template> </markdown-field> </div> </template> diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js index d76425c96b7..01295874e56 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js +++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js @@ -14,13 +14,7 @@ import axios from '~/lib/utils/axios_utils'; Vue.use(Translate); -export default () => { - const { dataset } = document.querySelector('.js-pipeline-details-vue'); - - const mediator = new PipelinesMediator({ endpoint: dataset.endpoint }); - - mediator.fetchPipeline(); - +const createPipelinesDetailApp = mediator => { // eslint-disable-next-line no-new new Vue({ el: '#js-pipeline-graph-vue', @@ -50,7 +44,9 @@ export default () => { }); }, }); +}; +const createPipelineHeaderApp = mediator => { // eslint-disable-next-line no-new new Vue({ el: '#js-pipeline-header-vue', @@ -94,7 +90,9 @@ export default () => { }); }, }); +}; +const createPipelinesTabs = dataset => { const tabsElement = document.querySelector('.pipelines-tabs'); const testReportsEnabled = window.gon && window.gon.features && window.gon.features.junitPipelineView; @@ -119,27 +117,40 @@ export default () => { tabsElement.addEventListener('click', tabClickHandler); } + } +}; - // eslint-disable-next-line no-new - new Vue({ - el: '#js-pipeline-tests-detail', - components: { - TestReports, - }, - render(createElement) { - return createElement('test-reports'); - }, - }); +const createTestDetails = detailsEndpoint => { + // eslint-disable-next-line no-new + new Vue({ + el: '#js-pipeline-tests-detail', + components: { + TestReports, + }, + render(createElement) { + return createElement('test-reports'); + }, + }); - axios - .get(dataset.testReportsCountEndpoint) - .then(({ data }) => { - if (!data.total_count) { - return; - } + axios + .get(detailsEndpoint) + .then(({ data }) => { + if (!data.total_count) { + return; + } - document.querySelector('.js-test-report-badge-counter').innerHTML = data.total_count; - }) - .catch(() => {}); - } + document.querySelector('.js-test-report-badge-counter').innerHTML = data.total_count; + }) + .catch(() => {}); +}; + +export default () => { + const { dataset } = document.querySelector('.js-pipeline-details-vue'); + const mediator = new PipelinesMediator({ endpoint: dataset.endpoint }); + mediator.fetchPipeline(); + + createPipelinesDetailApp(mediator); + createPipelineHeaderApp(mediator); + createPipelinesTabs(dataset); + createTestDetails(dataset.testReportsCountEndpoint); }; diff --git a/app/assets/stylesheets/pages/alert_management/list.scss b/app/assets/stylesheets/pages/alert_management/list.scss index 3fda66adc87..dc181342def 100644 --- a/app/assets/stylesheets/pages/alert_management/list.scss +++ b/app/assets/stylesheets/pages/alert_management/list.scss @@ -56,7 +56,7 @@ min-height: 68px; &:last-child { - background-color: $gray-normal; + background-color: $gray-10; &::before { content: none !important; diff --git a/app/controllers/admin/ci/variables_controller.rb b/app/controllers/admin/ci/variables_controller.rb new file mode 100644 index 00000000000..ca9b393550d --- /dev/null +++ b/app/controllers/admin/ci/variables_controller.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +class Admin::Ci::VariablesController < Admin::ApplicationController + def show + respond_to do |format| + format.json { render_instance_variables } + end + end + + def update + service = Ci::UpdateInstanceVariablesService.new(variables_params) + + if service.execute + respond_to do |format| + format.json { render_instance_variables } + end + else + respond_to do |format| + format.json { render_error(service.errors) } + end + end + end + + private + + def variables + @variables ||= Ci::InstanceVariable.all + end + + def render_instance_variables + render status: :ok, + json: { + variables: Ci::InstanceVariableSerializer.new.represent(variables) + } + end + + def render_error(errors) + render status: :bad_request, json: errors + end + + def variables_params + params.permit(variables_attributes: [*variable_params_attributes]) + end + + def variable_params_attributes + %i[id variable_type key secret_value protected masked _destroy] + end +end diff --git a/app/models/release.rb b/app/models/release.rb index 20f34e9286f..a0245105cd9 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -34,8 +34,6 @@ class Release < ApplicationRecord delegate :repository, to: :project - after_commit :notify_new_release, on: :create, unless: :importing? - MAX_NUMBER_TO_DISPLAY = 3 def to_param @@ -92,10 +90,6 @@ class Release < ApplicationRecord repository.find_tag(tag) end end - - def notify_new_release - NewReleaseWorker.perform_async(id) - end end Release.prepend_if_ee('EE::Release') diff --git a/app/serializers/ci/basic_variable_entity.rb b/app/serializers/ci/basic_variable_entity.rb new file mode 100644 index 00000000000..dad59e8735b --- /dev/null +++ b/app/serializers/ci/basic_variable_entity.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Ci + class BasicVariableEntity < Grape::Entity + expose :id + expose :key + expose :value + expose :variable_type + + expose :protected?, as: :protected + expose :masked?, as: :masked + end +end diff --git a/app/serializers/ci/instance_variable_serializer.rb b/app/serializers/ci/instance_variable_serializer.rb new file mode 100644 index 00000000000..b0b49aecdbd --- /dev/null +++ b/app/serializers/ci/instance_variable_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Ci + class InstanceVariableSerializer < BaseSerializer + entity BasicVariableEntity + end +end diff --git a/app/serializers/group_variable_entity.rb b/app/serializers/group_variable_entity.rb index 622106458c3..4f44723fefe 100644 --- a/app/serializers/group_variable_entity.rb +++ b/app/serializers/group_variable_entity.rb @@ -1,11 +1,4 @@ # frozen_string_literal: true -class GroupVariableEntity < Grape::Entity - expose :id - expose :key - expose :value - expose :variable_type - - expose :protected?, as: :protected - expose :masked?, as: :masked +class GroupVariableEntity < Ci::BasicVariableEntity end diff --git a/app/serializers/variable_entity.rb b/app/serializers/variable_entity.rb index 017035fa117..9b0db371acb 100644 --- a/app/serializers/variable_entity.rb +++ b/app/serializers/variable_entity.rb @@ -1,12 +1,5 @@ # frozen_string_literal: true -class VariableEntity < Grape::Entity - expose :id - expose :key - expose :value - expose :variable_type - - expose :protected?, as: :protected - expose :masked?, as: :masked +class VariableEntity < Ci::BasicVariableEntity expose :environment_scope end diff --git a/app/services/ci/update_instance_variables_service.rb b/app/services/ci/update_instance_variables_service.rb new file mode 100644 index 00000000000..ee513647d08 --- /dev/null +++ b/app/services/ci/update_instance_variables_service.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +# This class is a simplified version of assign_nested_attributes_for_collection_association from ActiveRecord +# https://github.com/rails/rails/blob/v6.0.2.1/activerecord/lib/active_record/nested_attributes.rb#L466 + +module Ci + class UpdateInstanceVariablesService + UNASSIGNABLE_KEYS = %w(id _destroy).freeze + + def initialize(params) + @params = params[:variables_attributes] + end + + def execute + instantiate_records + persist_records + end + + def errors + @records.to_a.flat_map { |r| r.errors.full_messages } + end + + private + + attr_reader :params + + def existing_records_by_id + @existing_records_by_id ||= Ci::InstanceVariable + .all + .index_by { |var| var.id.to_s } + end + + def instantiate_records + @records = params.map do |attributes| + find_or_initialize_record(attributes).tap do |record| + record.assign_attributes(attributes.except(*UNASSIGNABLE_KEYS)) + record.mark_for_destruction if has_destroy_flag?(attributes) + end + end + end + + def find_or_initialize_record(attributes) + id = attributes[:id].to_s + + if id.blank? + Ci::InstanceVariable.new + else + existing_records_by_id.fetch(id) { raise ActiveRecord::RecordNotFound } + end + end + + def persist_records + Ci::InstanceVariable.transaction do + success = @records.map do |record| + if record.marked_for_destruction? + record.destroy + else + record.save + end + end.all? + + raise ActiveRecord::Rollback unless success + + success + end + end + + def has_destroy_flag?(hash) + Gitlab::Utils.to_boolean(hash['_destroy']) + end + end +end diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb index 9a0a876454f..81ca9d6d123 100644 --- a/app/services/releases/create_service.rb +++ b/app/services/releases/create_service.rb @@ -47,11 +47,17 @@ module Releases release.save! + notify_create_release(release) + success(tag: tag, release: release) rescue => e error(e.message, 400) end + def notify_create_release(release) + NotificationService.new.async.send_new_release_notifications(release) + end + def build_release(tag) project.releases.build( name: name, diff --git a/app/workers/new_release_worker.rb b/app/workers/new_release_worker.rb index 3c19e5f3d2b..fa4703d10f2 100644 --- a/app/workers/new_release_worker.rb +++ b/app/workers/new_release_worker.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# TODO: Worker can be removed in 13.2: +# https://gitlab.com/gitlab-org/gitlab/-/issues/218231 class NewReleaseWorker # rubocop:disable Scalability/IdempotentWorker include ApplicationWorker diff --git a/changelogs/unreleased/14108-instance-level-ci-variables-controller.yml b/changelogs/unreleased/14108-instance-level-ci-variables-controller.yml new file mode 100644 index 00000000000..a95a6d3b9c8 --- /dev/null +++ b/changelogs/unreleased/14108-instance-level-ci-variables-controller.yml @@ -0,0 +1,5 @@ +--- +title: Add admin controller actions for interacting with instance variables +merge_request: 30385 +author: +type: added diff --git a/changelogs/unreleased/alert-management-colour.yml b/changelogs/unreleased/alert-management-colour.yml new file mode 100644 index 00000000000..c8541b5bcd4 --- /dev/null +++ b/changelogs/unreleased/alert-management-colour.yml @@ -0,0 +1,5 @@ +--- +title: Update alert management table background colour to correct gray +merge_request: 32068 +author: +type: other diff --git a/changelogs/unreleased/mv-to-service.yml b/changelogs/unreleased/mv-to-service.yml new file mode 100644 index 00000000000..ff279122a17 --- /dev/null +++ b/changelogs/unreleased/mv-to-service.yml @@ -0,0 +1,5 @@ +--- +title: Move release notification from model callbacks to service +merge_request: 29853 +author: Ravishankar +type: performance diff --git a/changelogs/unreleased/update-deprecated-slot-syntax-in-app-assets-javascripts-issue_show-compon.yml b/changelogs/unreleased/update-deprecated-slot-syntax-in-app-assets-javascripts-issue_show-compon.yml new file mode 100644 index 00000000000..7fcf63f7fca --- /dev/null +++ b/changelogs/unreleased/update-deprecated-slot-syntax-in-app-assets-javascripts-issue_show-compon.yml @@ -0,0 +1,5 @@ +--- +title: Update deprecated slot syntax in ./app/assets/javascripts/issue_show/components/fields/description.vue +merge_request: 31979 +author: Gilang Gumilar +type: other diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 5809be67556..f3b7fb5ed45 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -154,6 +154,10 @@ namespace :admin do end end + namespace :ci do + resource :variables, only: [:show, :update] + end + concerns :clusterable get '/dashboard/stats', to: 'dashboard#stats' diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md index 3adfc83ce06..293414a6e5e 100644 --- a/doc/administration/geo/replication/troubleshooting.md +++ b/doc/administration/geo/replication/troubleshooting.md @@ -499,7 +499,7 @@ to start again from scratch, there are a few steps that can help you: 1. Refresh Foreign Data Wrapper tables - ```sh + ```shell gitlab-rake geo:db:refresh_foreign_tables ``` diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md index 9efee00e468..fcd69464b13 100644 --- a/doc/administration/incoming_email.md +++ b/doc/administration/incoming_email.md @@ -226,6 +226,9 @@ incoming_email: Example configuration for Gmail/G Suite. Assumes mailbox `gitlab-incoming@gmail.com`. +NOTE: **Note:** +`incoming_email_email` cannot be a Gmail alias account. + Example for Omnibus installs: ```ruby diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index f0d4d216d8e..1e7166da38f 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -716,7 +716,7 @@ built-in command: If you did not change the default location of the configuration file, run: -```sh +```shell sudo gitlab-ctl registry-garbage-collect ``` @@ -725,7 +725,7 @@ layers you have stored. If you changed the location of the Container Registry `config.yml`: -```sh +```shell sudo gitlab-ctl registry-garbage-collect /path/to/config.yml ``` @@ -749,7 +749,7 @@ referenced by the registry tag. The `registry-garbage-collect` command supports `-m` switch to allow you to remove all unreferenced manifests and layers that are not directly accessible via `tag`: -```sh +```shell sudo gitlab-ctl registry-garbage-collect -m ``` @@ -787,7 +787,7 @@ To enable the read-only mode: 1. Save and reconfigure GitLab: - ```sh + ```shell sudo gitlab-ctl reconfigure ``` @@ -795,7 +795,7 @@ To enable the read-only mode: 1. Next, trigger one of the garbage collect commands: - ```sh + ```shell # Recycling unused tags sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml @@ -822,7 +822,7 @@ To enable the read-only mode: 1. Save and reconfigure GitLab: - ```sh + ```shell sudo gitlab-ctl reconfigure ``` diff --git a/doc/administration/static_objects_external_storage.md b/doc/administration/static_objects_external_storage.md index f649a1ebcd2..973f4304115 100644 --- a/doc/administration/static_objects_external_storage.md +++ b/doc/administration/static_objects_external_storage.md @@ -63,7 +63,7 @@ other CDNs or Function as a Service (FaaS) systems should work using the same pr `pwgen -cn1 64` on a UNIX machine). Save this token for the admin panel, as described in the [configuring](#configuring) section. - ```js + ```javascript const ORIGIN_HOSTNAME = 'gitlab.installation.com' // FIXME: SET CORRECT VALUE const STORAGE_TOKEN = 'very-secure-token' // FIXME: SET CORRECT VALUE const CACHE_PRIVATE_OBJECTS = false diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md index 0413e5ce953..dcd1df2f423 100644 --- a/doc/administration/troubleshooting/log_parsing.md +++ b/doc/administration/troubleshooting/log_parsing.md @@ -16,19 +16,19 @@ include use cases targeted for parsing GitLab log files. #### Pipe colorized `jq` output into `less` -```sh +```shell jq . <FILE> -C | less -R ``` #### Search for a term and pretty-print all matching lines -```sh +```shell grep <TERM> <FILE> | jq . ``` #### Skip invalid lines of JSON -```sh +```shell jq -cR 'fromjson?' file.json | jq <COMMAND> ``` @@ -39,49 +39,49 @@ This skips over all invalid lines and parses the rest. #### Find all requests with a 5XX status code -```sh +```shell jq 'select(status >= 500)' <FILE> ``` #### Top 10 slowest requests -```sh +```shell jq -s 'sort_by(-.duration) | limit(10; .[])' <FILE> ``` #### Find and pretty print all requests related to a project -```sh +```shell grep <PROJECT_NAME> <FILE> | jq . ``` #### Find all requests with a total duration > 5 seconds -```sh +```shell jq 'select(.duration > 5000)' <FILE> ``` #### Find all project requests with more than 5 rugged calls -```sh +```shell grep <PROJECT_NAME> <FILE> | jq 'select(.rugged_calls > 5)' ``` #### Find all requests with a Gitaly duration > 10 seconds -```sh +```shell jq 'select(.gitaly_duration > 10000)' <FILE> ``` #### Find all requests with a queue duration > 10 seconds -```sh +```shell jq 'select(.queue_duration > 10000)' <FILE> ``` #### Top 10 requests by # of Gitaly calls -```sh +```shell jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE> ``` @@ -89,7 +89,7 @@ jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; #### Print the top three controller methods by request volume and their three longest durations -```sh +```shell jq -s -r 'group_by(.controller+.action) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration) | "CT: \(length)\tMETHOD: \(.[0].controller)#\(.[0].action)\tDURS: \(.[0].duration), \(.[1].duration), \(.[2].duration)"' production_json.log ``` @@ -105,7 +105,7 @@ CT: 1328 METHOD: Projects::NotesController#index DURS: 403.99, 386.29, 384.3 #### Print top three routes with request count and their three longest durations -```sh +```shell jq -s -r 'group_by(.route) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration) | "CT: \(length)\tROUTE: \(.[0].route)\tDURS: \(.[0].duration), \(.[1].duration), \(.[2].duration)"' api_json.log ``` @@ -121,25 +121,25 @@ CT: 190 ROUTE: /api/:version/projects/:id/repository/commits DURS: 1079.02, #### Find all Gitaly requests sent from web UI -```sh +```shell jq 'select(."grpc.meta.client_name" == "gitlab-web")' current ``` #### Find all failed Gitaly requests -```sh +```shell jq 'select(."grpc.code" != null and ."grpc.code" != "OK")' current ``` #### Find all requests that took longer than 30 seconds -```sh +```shell jq 'select(."grpc.time_ms" > 30000)' current ``` #### Print top three projects by request volume and their three longest durations -```sh +```shell jq -s -r 'map(select(."grpc.request.glProjectPath" != null and ."grpc.request.glProjectPath" != "" and ."grpc.time_ms" != null)) | group_by(."grpc.request.glProjectPath") | sort_by(-length) | limit(3; .[]) | sort_by(-."grpc.time_ms") | "CT: \(length)\tPROJECT: \(.[0]."grpc.request.glProjectPath")\tDURS: \(.[0]."grpc.time_ms"), \(.[1]."grpc.time_ms"), \(.[2]."grpc.time_ms")"' current ``` diff --git a/doc/api/freeze_periods.md b/doc/api/freeze_periods.md index d5f165015e7..ee5e657c945 100644 --- a/doc/api/freeze_periods.md +++ b/doc/api/freeze_periods.md @@ -11,7 +11,7 @@ interact with the Freeze Period API endpoints. ## List Freeze Periods -Paginated list of Freeze Periods, sorted by `created_at`. +Paginated list of Freeze Periods, sorted by `created_at` in ascending order. ```plaintext GET /projects/:id/freeze_periods diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md index 3a79268e889..6faaa95116d 100644 --- a/doc/api/pipeline_schedules.md +++ b/doc/api/pipeline_schedules.md @@ -297,7 +297,7 @@ POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/play Example request: -```sh +```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/42/pipeline_schedules/1/play ``` diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md index ecd35239e00..12b453007b0 100644 --- a/doc/api/remote_mirrors.md +++ b/doc/api/remote_mirrors.md @@ -17,7 +17,7 @@ GET /projects/:id/remote_mirrors Example request: -```sh +```shell curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/42/remote_mirrors' ``` @@ -63,7 +63,7 @@ POST /projects/:id/remote_mirrors Example request: -```sh +```shell curl --request POST --data "url=https://username:token@example.com/gitlab/example.git" --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/42/remote_mirrors' ``` @@ -104,7 +104,7 @@ PUT /projects/:id/remote_mirrors/:mirror_id Example request: -```sh +```shell curl --request PUT --data "enabled=false" --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/42/remote_mirrors/101486' ``` diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md index 6b4fd1cbf40..373c5a4ee7d 100644 --- a/doc/development/documentation/feature_flags.md +++ b/doc/development/documentation/feature_flags.md @@ -49,7 +49,7 @@ For feature flags disabled by default, if they can be used by end users: For example, for a feature disabled by default, disabled on GitLab.com, and not ready for production use: -````md +````markdown # Feature Name > - [Introduced](link-to-issue) in GitLab 12.0. @@ -93,7 +93,7 @@ For features that became enabled by default: For example, for a feature initially deployed disabled by default, that became enabled by default, that is enabled on GitLab.com, and ready for production use: -````md +````markdown # Feature Name > - [Introduced](link-to-issue) in GitLab 12.0. @@ -138,7 +138,7 @@ For features enabled by default: For example, for a feature enabled by default, enabled on GitLab.com, and ready for production use: -````md +````markdown # Feature Name > - [Introduced](link-to-issue) in GitLab 12.0. @@ -177,7 +177,7 @@ Once the feature is ready and the flag has been removed, clean up the documentation. Remove the feature flag mention keeping only a note that mentions the flag in the version history notes: -````md +````markdown # Feature Name > - [Introduced](link-to-issue) in GitLab 12.0. diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index ca393fbb63c..256d3f5d86c 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -79,7 +79,7 @@ change prior to merging. If you indeed need to change a document's location, do not remove the old document, but instead replace all of its content with the following: -```md +```markdown --- redirect_to: '../path/to/file/index.md' --- @@ -93,7 +93,7 @@ The `redirect_to` variable supports both full and relative URLs, for example `https://docs.gitlab.com/ee/path/to/file.html`, `../path/to/file.html`, `path/to/file.md`. It ensures that the redirect will work for <https://docs.gitlab.com> and any `*.md` paths will be compiled to `*.html`. -The new line underneath the frontmatter informs the user that the document +The new line underneath the front matter informs the user that the document changed location and is useful for someone that browses that file from the repository. For example, if you move `doc/workflow/lfs/index.md` to @@ -102,7 +102,7 @@ For example, if you move `doc/workflow/lfs/index.md` to 1. Copy `doc/workflow/lfs/index.md` to `doc/administration/lfs.md` 1. Replace the contents of `doc/workflow/lfs/index.md` with: - ```md + ```markdown --- redirect_to: '../../administration/lfs.md' --- @@ -148,12 +148,12 @@ Disqus uses an identifier per page, and for <https://docs.gitlab.com>, the page is configured to be the page URL. Therefore, when we change the document location, we need to preserve the old URL as the same Disqus identifier. -To do that, add to the frontmatter the variable `disqus_identifier`, -using the old URL as value. For example, let's say I moved the document +To do that, add to the front matter the variable `disqus_identifier`, +using the old URL as value. For example, let's say we moved the document available under `https://docs.gitlab.com/my-old-location/README.html` to a new location, `https://docs.gitlab.com/my-new-location/index.html`. -Into the **new document** frontmatter add the following: +Into the **new document** front matter, we add the following: ```yaml --- @@ -298,8 +298,8 @@ To preview your changes to documentation locally, follow this The live preview is currently enabled for the following projects: -- <https://gitlab.com/gitlab-org/gitlab> -- <https://gitlab.com/gitlab-org/gitlab-runner> +- [`gitlab`](https://gitlab.com/gitlab-org/gitlab) +- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner) If your merge request has docs changes, you can use the manual `review-docs-deploy` job to deploy the docs review app for your merge request. @@ -485,14 +485,14 @@ markdownlint can be used [on the command line](https://github.com/igorshubovych/ either on a single Markdown file or on all Markdown files in a project. For example, to run markdownlint on all documentation in the [`gitlab` project](https://gitlab.com/gitlab-org/gitlab), run the following commands from within your `gitlab` project root directory, which will -automatically detect the [`.markdownlint.json`](#markdownlint-configuration) config +automatically detect the [`.markdownlint.json`](#markdownlint-configuration) configuration file in the root of the project, and test all files in `/doc` and its subdirectories: ```shell markdownlint 'doc/**/*.md' ``` -If you wish to use a different config file, use the `-c` flag: +If you wish to use a different configuration file, use the `-c` flag: ```shell markdownlint -c <config-file-name> 'doc/**/*.md' @@ -506,7 +506,7 @@ such as: - [Atom](https://atom.io/packages/linter-node-markdownlint) It is best to use the [same configuration file](#markdownlint-configuration) as what -is in use in the four repos that are the sources for <https://docs.gitlab.com>. Each +is in use in the four repositories that are the sources for <https://docs.gitlab.com>. Each plugin/extension has different requirements regarding the configuration file, which is explained in each editor's docs. @@ -515,12 +515,12 @@ is explained in each editor's docs. Each formatting issue that markdownlint checks has an associated [rule](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules). These rules are configured in the `.markdownlint.json` files located in the root of -four repos that are the sources for <https://docs.gitlab.com>: +four repositories that are the sources for <https://docs.gitlab.com>: -- <https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json> -- <https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json> -- <https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json> -- <https://gitlab.com/charts/gitlab/blob/master/.markdownlint.json> +- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json) +- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json) +- [`omnibus-gitlab`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json) +- [`charts`](https://gitlab.com/charts/gitlab/blob/master/.markdownlint.json) By default all rules are enabled, so the configuration file is used to disable unwanted rules, and also to configure optional parameters for enabled rules as needed. You can @@ -550,7 +550,7 @@ You can also [configure the text editor of your choice](https://errata-ai.github.io/vale/#local-use-by-a-single-writer) to display the results. -Vale's test results are not currently displayed in CI, but may be displayed in the future. +Vale's test results [are displayed](#testing) in CI pipelines. ##### Disable a Vale test @@ -573,5 +573,5 @@ For more information, see [Vale's documentation](https://errata-ai.gitbook.io/va GitLab uses [Danger](https://github.com/danger/danger) for some elements in code review. For docs changes in merge requests, whenever a change to files under `/doc` is made, Danger Bot leaves a comment with further instructions about the documentation -process. This is configured in the Dangerfile in the GitLab repo under +process. This is configured in the `Dangerfile` in the GitLab repository under [/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation). diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md index 84ba47eba78..d19383bee27 100644 --- a/doc/development/documentation/structure.md +++ b/doc/development/documentation/structure.md @@ -20,7 +20,7 @@ Every feature or use case document should include the following content in the f with exceptions and details noted below and in the template included on this page. - **Title**: Top-level heading with the feature name, or a use case name, which would start with - a verb, like Configuring, Enabling, etc. + a verb, like Configuring, Enabling, and so on. - **Introduction**: A couple sentences about the subject matter and what's to be found on this page. Describe what the feature or topic is, what it does, and in what context it should be used. There is no need to add a title called "Introduction" or "Overview," because people rarely @@ -41,7 +41,7 @@ and other logical divisions such as pre- and post-deployment steps. To start a new document, respect the file tree and file name guidelines, as well as the style guidelines. Use the following template: -```md +```markdown <!--Follow the Style Guide when working on this document. https://docs.gitlab.com/ee/development/documentation/styleguide.html When done, remove all of this commented-out text, except a commented-out Troubleshooting section, which, if empty, can be left in place to encourage future use.--> @@ -130,7 +130,7 @@ Notes: ## Help and feedback section The "help and feedback" section (introduced by [!319](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319)) displayed at the end of each document -can be omitted from the doc by adding a key into the its frontmatter: +can be omitted from the doc by adding a key into the its front matter: ```yaml --- @@ -148,7 +148,7 @@ We also have integrated the docs site with Disqus (introduced by allowing our users to post comments. To omit only the comments from the feedback section, use the following -key on the frontmatter: +key on the front matter: ```yaml --- @@ -159,7 +159,7 @@ comments: false We are only hiding comments in main index pages, such as [the main documentation index](../../README.md), since its content is too broad to comment on. Before omitting Disqus, you must check with a technical writer. -Note that once `feedback: false` is added to the frontmatter, it will automatically omit +Note that once `feedback: false` is added to the front matter, it will automatically omit Disqus, therefore, don't add both keys to the same document. The click events in the feedback section are tracked with Google Tag Manager. The diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index c75eccd71c1..22c1d790b07 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -390,7 +390,7 @@ tenses, words, and phrases: - Insert an empty line for new paragraphs. - Insert an empty line between different markups (for example, after every paragraph, header, list, and so on). Example: - ```md + ```markdown ## Header Paragraph. @@ -447,7 +447,7 @@ Only use ordered lists when their items describe a sequence of steps to follow. Do: -```md +```markdown These are the steps to do something: 1. First, do the first step. @@ -457,7 +457,7 @@ These are the steps to do something: Don't: -```md +```markdown This is a list of available features: 1. Feature 1 @@ -483,7 +483,7 @@ This is a list of available features: all with a period. - Separate list items from explanatory text with a colon (`:`). For example: - ```md + ```markdown The list is as follows: - First item: this explains the first item. @@ -630,7 +630,7 @@ page), use the following phrases (based on the SVG icons): ## Quotes -Valid for Markdown content only, not for frontmatter entries: +Valid for Markdown content only, not for front matter entries: - Standard quotes: double quotes (`"`). Example: "This is wrapped in double quotes". - Quote within a quote: double quotes (`"`) wrap single quotes (`'`). Example: "I am 'quoting' something within a quote". @@ -792,7 +792,7 @@ Instead: Example: -```md +```markdown For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-foss/issues/<issue_number>`. ``` @@ -908,7 +908,7 @@ Do not upload videos to the product repositories. [Link](#link-to-video) or [emb To link out to a video, include a YouTube icon so that readers can quickly and easily scan the page for videos before reading: -```md +```markdown <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> For an overview, see [Video Title](link-to-video). ``` @@ -1082,7 +1082,7 @@ This will ensure that the source Markdown remains readable and should help with The following are examples of source Markdown for menu items with their published output: -```md +```markdown 1. Go to **{home}** **Project overview > Details** 1. Go to **{doc-text}** **Repository > Branches** 1. Go to **{issues}** **Issues > List** @@ -1143,7 +1143,7 @@ of users. Weigh the costs of distracting users to whom the content is not relevant against the cost of users missing the content if it were not expressed as a note. -```md +```markdown NOTE: **Note:** This is something to note. ``` @@ -1155,7 +1155,7 @@ This is something to note. ### Tip -```md +```markdown TIP: **Tip:** This is a tip. ``` @@ -1167,7 +1167,7 @@ This is a tip. ### Caution -```md +```markdown CAUTION: **Caution:** This is something to be cautious about. ``` @@ -1179,7 +1179,7 @@ This is something to be cautious about. ### Danger -```md +```markdown DANGER: **Danger:** This is a breaking change, a bug, or something very important to note. ``` @@ -1193,7 +1193,7 @@ This is a breaking change, a bug, or something very important to note. For highlighting a text within a blue blockquote, use this format: -```md +```markdown > This is a blockquote. ``` @@ -1205,7 +1205,7 @@ If the text spans across multiple lines it's OK to split the line. For multiple paragraphs, use the symbol `>` before every line: -```md +```markdown > This is the first paragraph. > > This is the second paragraph. @@ -1298,14 +1298,14 @@ a helpful link back to how the feature was developed. - If listing information for multiple version as a feature evolves, add the information to a block-quoted bullet list. For example: - ```md + ```markdown > - [Introduced](<link-to-issue>) in GitLab 11.3. > - Enabled by default in GitLab 11.4. ``` - If a feature is moved to another tier: - ```md + ```markdown > - [Introduced](<link-to-issue>) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.5. > - [Moved](<link-to-issue>) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8. > - [Moved](<link-to-issue>) to GitLab Core in 12.0. @@ -1417,7 +1417,7 @@ avoid duplication, link to the special document that can be found in [`doc/administration/restart_gitlab.md`](../../administration/restart_gitlab.md). Usually the text will read like: -```md +```markdown Save the file and [reconfigure GitLab](../../administration/restart_gitlab.md) for the changes to take effect. ``` @@ -1453,7 +1453,7 @@ When there is a list of steps to perform, usually that entails editing the configuration file and reconfiguring/restarting GitLab. In such case, follow the style below as a guide: -````md +````markdown **For Omnibus installations** 1. Edit `/etc/gitlab/gitlab.rb`: @@ -1591,7 +1591,7 @@ You can use the following fake tokens as examples. Use the following table headers to describe the methods. Attributes should always be in code blocks using backticks (`` ` ``). -```md +```markdown | Attribute | Type | Required | Description | |:----------|:-----|:---------|:------------| ``` diff --git a/doc/development/fe_guide/droplab/droplab.md b/doc/development/fe_guide/droplab/droplab.md index 4d7c882dc09..83bc4216403 100644 --- a/doc/development/fe_guide/droplab/droplab.md +++ b/doc/development/fe_guide/droplab/droplab.md @@ -26,7 +26,7 @@ If you do not provide any arguments, it will globally query and instantiate all <ul> ``` -```js +```javascript const droplab = new DropLab(); droplab.init(); ``` @@ -47,7 +47,7 @@ You can add static list items. <ul> ``` -```js +```javascript const droplab = new DropLab(); droplab.init(); ``` @@ -65,7 +65,7 @@ a non-global instance of DropLab using the `DropLab.prototype.init` method. <ul> ``` -```js +```javascript const trigger = document.getElementById('trigger'); const list = document.getElementById('list'); @@ -83,7 +83,7 @@ You can also add hooks to an existing DropLab instance using `DropLab.prototype. <ul id="list" data-dropdown><!-- ... --><ul> ``` -```js +```javascript const droplab = new DropLab(); droplab.init(); @@ -114,7 +114,7 @@ for all `data-dynamic` dropdown lists tracked by that DropLab instance. </ul> ``` -```js +```javascript const droplab = new DropLab(); droplab.init().addData([{ @@ -137,7 +137,7 @@ the data as the second argument and the `id` of the trigger element as the first </ul> ``` -```js +```javascript const droplab = new DropLab(); droplab.init().addData('trigger', [{ @@ -167,7 +167,7 @@ dropdown lists, one of which is dynamic. </div> ``` -```js +```javascript const droplab = new DropLab(); droplab.init().addData('trigger', [{ @@ -224,7 +224,7 @@ Some plugins require configuration values, the config object can be passed as th <ul id="list" data-dropdown><!-- ... --><ul> ``` -```js +```javascript const droplab = new DropLab(); const trigger = document.getElementById('trigger'); @@ -249,7 +249,7 @@ droplab.init(trigger, list, [droplabAjax], { When plugins are initialised for a droplab trigger+dropdown, DropLab will call the plugins `init` function, so this must be implemented in the plugin. -```js +```javascript class MyPlugin { static init() { this.someProp = 'someProp'; diff --git a/doc/development/fe_guide/droplab/plugins/ajax.md b/doc/development/fe_guide/droplab/plugins/ajax.md index 77ba6f739e6..abc208e7568 100644 --- a/doc/development/fe_guide/droplab/plugins/ajax.md +++ b/doc/development/fe_guide/droplab/plugins/ajax.md @@ -18,7 +18,7 @@ Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or `Dro <ul id="list" data-dropdown><!-- ... --><ul> ``` -```js +```javascript const droplab = new DropLab(); const trigger = document.getElementById('trigger'); diff --git a/doc/development/fe_guide/droplab/plugins/filter.md b/doc/development/fe_guide/droplab/plugins/filter.md index b867394a241..876149e4872 100644 --- a/doc/development/fe_guide/droplab/plugins/filter.md +++ b/doc/development/fe_guide/droplab/plugins/filter.md @@ -18,7 +18,7 @@ Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or `D <ul> ``` -```js +```javascript const droplab = new DropLab(); const trigger = document.getElementById('trigger'); diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md index db492da478a..9b2e1e8faab 100644 --- a/doc/development/fe_guide/droplab/plugins/input_setter.md +++ b/doc/development/fe_guide/droplab/plugins/input_setter.md @@ -23,7 +23,7 @@ You can also set the `InputSetter` config to an array of objects, which will all <ul> ``` -```js +```javascript const droplab = new DropLab(); const trigger = document.getElementById('trigger'); diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index e839f6bacd3..caf84d04490 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -212,7 +212,7 @@ Read more about local state management with Apollo in the [Vue Apollo documentat When Apollo Client is used within Vuex and fetched data is stored in the Vuex store, there is no need in keeping Apollo Client cache enabled. Otherwise we would have data from the API stored in two places - Vuex store and Apollo Client cache. More to say, with Apollo default settings, a subsequent fetch from the GraphQL API could result in fetching data from Apollo cache (in the case where we have the same query and variables). To prevent this behavior, we need to disable Apollo Client cache passing a valid `fetchPolicy` option to its constructor: -```js +```javascript import fetchPolicies from '~/graphql_shared/fetch_policy_constants'; export const gqClient = createGqClient( diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md index e9f1a702fdf..7ab48db7f76 100644 --- a/doc/development/fe_guide/vue3_migration.md +++ b/doc/development/fe_guide/vue3_migration.md @@ -111,7 +111,7 @@ export default { </template> ``` -```js +```javascript // MyAwesomeComponent.spec.js import SomeChildComponent from '~/some_child_component.vue' diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md index ba79c641995..a81e656fc27 100644 --- a/doc/development/i18n/externalization.md +++ b/doc/development/i18n/externalization.md @@ -131,7 +131,7 @@ You can mark that content for translation with: In JavaScript we added the `__()` (double underscore parenthesis) function that you can import from the `~/locale` file. For instance: -```js +```javascript import { __ } from '~/locale'; const label = __('Subscribe'); ``` @@ -167,7 +167,7 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s - In JavaScript (when Vue cannot be used): - ```js + ```javascript import { __, sprintf } from '~/locale'; sprintf(__('Hello %{username}'), { username: 'Joe' }); // => 'Hello Joe' @@ -180,7 +180,7 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s escape any interpolated dynamic values yourself, for instance using `escape` from `lodash`. - ```js + ```javascript import { escape } from 'lodash'; import { __, sprintf } from '~/locale'; @@ -220,14 +220,14 @@ For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make s - In JavaScript: - ```js + ```javascript n__('Apple', 'Apples', 3) // => 'Apples' ``` Using interpolation: - ```js + ```javascript n__('Last day', 'Last %d days', x) // => When x == 1: 'Last day' // => When x == 2: 'Last 2 days' @@ -274,7 +274,7 @@ Namespaces should be PascalCase. - In JavaScript: - ```js + ```javascript s__('OpenedNDaysAgo|Opened') ``` @@ -285,7 +285,7 @@ guidelines for more details](translation.md#namespaced-strings). - In JavaScript: -```js +```javascript import { createDateTimeFormat } from '~/locale'; const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' }); @@ -372,7 +372,7 @@ structure is the same in all languages. For instance, the following: -```js +```javascript {{ s__("mrWidget|Set by") }} {{ author.name }} {{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }} @@ -380,7 +380,7 @@ For instance, the following: should be externalized as follows: -```js +```javascript {{ sprintf(s__("mrWidget|Set by %{author} to be merged automatically when the pipeline succeeds"), { author: author.name }) }} ``` @@ -439,7 +439,7 @@ This also applies when using links in between translated sentences, otherwise th - In JavaScript (when Vue cannot be used), instead of: - ```js + ```javascript {{ sprintf(s__("ClusterIntegration|Learn more about %{link}"), { link: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">zones</a>' @@ -449,7 +449,7 @@ This also applies when using links in between translated sentences, otherwise th Set the link starting and ending HTML fragments as placeholders like so: - ```js + ```javascript {{ sprintf(s__("ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}"), { linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">', diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 13a38a44cff..4cf546173de 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -51,7 +51,7 @@ or `db/post_migrate`, so if there are any migrations you don't want to commit to the schema, rename or remove them. If your branch is not targetting `master` you can set the `TARGET` environment variable. -```sh +```shell # Regenerate schema against `master` scripts/regenerate-schema diff --git a/doc/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md index 30cf8017820..dd336ad3a90 100644 --- a/doc/development/new_fe_guide/modules/dirty_submit.md +++ b/doc/development/new_fe_guide/modules/dirty_submit.md @@ -13,7 +13,7 @@ within the GitLab project. ## Usage -```js +```javascript import dirtySubmitFactory from './dirty_submit/dirty_submit_form'; new DirtySubmitForm(document.querySelector('form')); diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index b4d9d6d0b09..39ca846c1cc 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -184,7 +184,7 @@ Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/135236627> ```mermaid graph LR subgraph "No needed jobs"; - 1-1["danger-review (5.3 minutes)"]; + 1-1["danger-review (3.5 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" 1-50["docs lint (6.75 minutes)"]; click 1-50 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0" @@ -200,9 +200,9 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (5.3 minutes)"]; + 1-1["danger-review (3.5 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (4.4 minutes)"]; + 1-2["build-qa-image (3.4 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" 1-3["compile-assets pull-cache (9.06 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" @@ -210,7 +210,7 @@ graph RL; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["gitlab:assets:compile pull-cache (22 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (9.6 minutes)"]; + 1-6["setup-test-env (8.22 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; @@ -250,7 +250,7 @@ graph RL; click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0" 2_2-4["memory-on-boot (7.19 minutes)"]; click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0" - 2_2-5["webpack-dev-server (7.62 minutes)"]; + 2_2-5["webpack-dev-server (6.1 minutes)"]; click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0" subgraph "Needs `setup-test-env` & `compile-assets`"; 2_2-1 & 2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3; @@ -275,28 +275,28 @@ graph RL; click 2_5-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations" end - 3_1-1["jest (11.2 minutes)"]; + 3_1-1["jest (15 minutes)"]; class 3_1-1 criticalPath; click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0" - 3_1-2["karma (9.18 minutes)"]; + 3_1-2["karma (8 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0" - 3_1-3["jest-as-if-foss (14.8 minutes)"]; + 3_1-3["jest-as-if-foss (19.7 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0" - 3_1-4["karma-as-if-foss (8.25 minutes)"]; + 3_1-4["karma-as-if-foss (7.5 minutes)"]; click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0" subgraph "Needs `frontend-fixtures`"; 3_1-1 & 3_1-2 --> 2_2-2; 3_1-3 & 3_1-4 --> 2_2-3; end - 3_2-1["rspec:coverage (7.67 minutes)"]; + 3_2-1["rspec:coverage (6.5 minutes)"]; subgraph "Depends on `rspec` jobs"; 3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1; class 3_2-1 criticalPath; click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0" end - 4_1-1["coverage-frontend (5.39 minutes)"]; + 4_1-1["coverage-frontend (3.6 minutes)"]; subgraph "Needs `jest`"; 4_1-1 --> 3_1-1; class 4_1-1 criticalPath; @@ -313,9 +313,9 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (5.3 minutes)"]; + 1-1["danger-review (3.5 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (4.4 minutes)"]; + 1-2["build-qa-image (3.4 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" 1-3["compile-assets pull-cache (9.06 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" @@ -323,7 +323,7 @@ graph RL; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["gitlab:assets:compile pull-cache (22 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (9.6 minutes)"]; + 1-6["setup-test-env (8.22 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; @@ -364,7 +364,7 @@ graph RL; click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0" 2_2-4["memory-on-boot (7.19 minutes)"]; click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0" - 2_2-5["webpack-dev-server (7.62 minutes)"]; + 2_2-5["webpack-dev-server (6.1 minutes)"]; click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0" subgraph "Needs `setup-test-env` & `compile-assets`"; 2_2-1 & 2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3; @@ -397,28 +397,28 @@ graph RL; click 2_6-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914314&udv=0" end - 3_1-1["jest (11.2 minutes)"]; + 3_1-1["jest (15 minutes)"]; class 3_1-1 criticalPath; click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0" - 3_1-2["karma (9.18 minutes)"]; + 3_1-2["karma (8 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0" - 3_1-3["jest-as-if-foss (14.8 minutes)"]; + 3_1-3["jest-as-if-foss (19.7 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0" - 3_1-4["karma-as-if-foss (8.25 minutes)"]; + 3_1-4["karma-as-if-foss (7.5 minutes)"]; click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0" subgraph "Needs `frontend-fixtures`"; 3_1-1 & 3_1-3 --> 2_2-2; 3_1-2 & 3_1-4 --> 2_2-3; end - 3_2-1["rspec:coverage (7.67 minutes)"]; + 3_2-1["rspec:coverage (6.5 minutes)"]; subgraph "Depends on `rspec` jobs"; 3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1; class 3_2-1 criticalPath; click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0" end - 4_1-1["coverage-frontend (5.39 minutes)"]; + 4_1-1["coverage-frontend (3.6 minutes)"]; subgraph "Needs `jest`"; 4_1-1 --> 3_1-1; class 4_1-1 criticalPath; @@ -432,9 +432,9 @@ graph RL; click 3_3-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6721130&udv=0" end - 4_2-1["review-qa-smoke (7.29 minutes)"]; + 4_2-1["review-qa-smoke (8 minutes)"]; click 4_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6729805&udv=0" - 4_2-2["review-performance (3.83 minutes)"]; + 4_2-2["review-performance (4 minutes)"]; click 4_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356817&udv=0" 4_2-3["dast (18 minutes)"]; click 4_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356819&udv=0" @@ -453,9 +453,9 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (5.3 minutes)"]; + 1-1["danger-review (3.5 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (4.4 minutes)"]; + 1-2["build-qa-image (3.4 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" 1-3["compile-assets pull-cache (9.06 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" @@ -463,7 +463,7 @@ graph RL; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["gitlab:assets:compile pull-cache (22 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (9.6 minutes)"]; + 1-6["setup-test-env (8.22 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; diff --git a/doc/topics/airgap/index.md b/doc/topics/airgap/index.md index 78af867c9d1..854e0103a69 100644 --- a/doc/topics/airgap/index.md +++ b/doc/topics/airgap/index.md @@ -98,7 +98,7 @@ If it's not possible to follow the above method, the images can be transferred m #### Example image packager script -```sh +```shell #!/bin/bash set -ux @@ -120,7 +120,7 @@ done This example loads the images from a bastion host to an offline host. In certain configurations, physical media may be needed for such a transfer: -```sh +```shell #!/bin/bash set -ux diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md index 880b9087dc1..893f7ba7cde 100644 --- a/doc/topics/autodevops/upgrading_postgresql.md +++ b/doc/topics/autodevops/upgrading_postgresql.md @@ -39,7 +39,7 @@ being modified after the database dump is created. 1. Get the Kubernetes namespace for the environment. It typically looks like `<project-name>-<project-id>-<environment>`. In our example, the namespace is called `minimal-ruby-app-4349298-production`. - ```sh + ```shell $ kubectl get ns NAME STATUS AGE @@ -48,13 +48,13 @@ being modified after the database dump is created. 1. For ease of use, export the namespace name: - ```sh + ```shell export APP_NAMESPACE=minimal-ruby-app-4349298-production ``` 1. Get the deployment name for your application with the following command. In our example, the deployment name is `production`. - ```sh + ```shell $ kubectl get deployment --namespace "$APP_NAMESPACE" NAME READY UP-TO-DATE AVAILABLE AGE production 2/2 2 2 7d21h @@ -64,7 +64,7 @@ being modified after the database dump is created. 1. To prevent the database from being modified, set replicas to 0 for the deployment with the following command. We use the deployment name from the previous step (`deployments/<DEPLOYMENT_NAME>`). - ```sh + ```shell $ kubectl scale --replicas=0 deployments/production --namespace "$APP_NAMESPACE" deployment.extensions/production scaled ``` @@ -75,7 +75,7 @@ being modified after the database dump is created. 1. Get the service name for PostgreSQL. The name of the service should end with `-postgres`. In our example the service name is `production-postgres`. - ```sh + ```shell $ kubectl get svc --namespace "$APP_NAMESPACE" NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE production-auto-deploy ClusterIP 10.30.13.90 <none> 5000/TCP 7d14h @@ -84,7 +84,7 @@ being modified after the database dump is created. 1. Get the pod name for PostgreSQL with the following command. In our example, the pod name is `production-postgres-5db86568d7-qxlxv`. - ```sh + ```shell $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=production-postgres NAME READY STATUS RESTARTS AGE production-postgres-5db86568d7-qxlxv 1/1 Running 0 7d14h @@ -92,7 +92,7 @@ being modified after the database dump is created. 1. Connect to the pod with: - ```sh + ```shell kubectl exec -it production-postgres-5db86568d7-qxlxv --namespace "$APP_NAMESPACE" bash ``` @@ -104,7 +104,7 @@ being modified after the database dump is created. - You will be asked for the database password, the default is `testing-password`. - ```sh + ```shell ## Format is: # pg_dump -h SERVICE_NAME -U USERNAME DATABASE_NAME > /tmp/backup.sql @@ -115,7 +115,7 @@ being modified after the database dump is created. 1. Download the dump file with the following command: - ```sh + ```shell kubectl cp --namespace "$APP_NAMESPACE" production-postgres-5db86568d7-qxlxv:/tmp/backup.sql backup.sql ``` @@ -131,7 +131,7 @@ deleted causing the persistent volumes to be deleted as well. You can verify this by using the following command: -```sh +```shell $ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 8Gi RWO Delete Bound minimal-ruby-app-4349298-staging/staging-postgres standard 7d22h @@ -145,7 +145,7 @@ interested in keeping the volumes for the staging and production of the `minimal-ruby-app-4349298` application, the volume names here are `pvc-0da80c08-5239-11ea-9c8d-42010a8e0096` and `pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096`: -```sh +```shell $ kubectl patch pv pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' persistentvolume/pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 patched $ kubectl patch pv pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' @@ -192,7 +192,7 @@ TIP: **Tip:** You can also 1. Get the pod name for the new PostgreSQL, in our example, the pod name is `production-postgresql-0`: - ```sh + ```shell $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=postgresql NAME READY STATUS RESTARTS AGE production-postgresql-0 1/1 Running 0 19m @@ -200,13 +200,13 @@ TIP: **Tip:** You can also 1. Copy the dump file from the backup steps to the pod: - ```sh + ```shell kubectl cp --namespace "$APP_NAMESPACE" backup.sql production-postgresql-0:/tmp/backup.sql ``` 1. Connect to the pod: - ```sh + ```shell kubectl exec -it production-postgresql-0 --namespace "$APP_NAMESPACE" bash ``` @@ -216,7 +216,7 @@ TIP: **Tip:** You can also - `USERNAME` is the username you have configured for PostgreSQL. The default is `user`. - `DATABASE_NAME` is usually the environment name. - ```sh + ```shell ## Format is: # psql -U USERNAME -d DATABASE_NAME < /tmp/backup.sql diff --git a/doc/user/markdown.md b/doc/user/markdown.md index 38b496e638b..102eb1f8f53 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -228,7 +228,7 @@ To make PlantUML available in GitLab, a GitLab administrator needs to enable it > If this is not rendered correctly, [view it in GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#emoji). -```md +```markdown Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you: :zap: You can use emoji anywhere GFM is supported. :v: @@ -804,7 +804,7 @@ but_emphasis is_desired _here_ If you wish to emphasize only a part of a word, it can still be done with asterisks: -```md +```markdown perform*complicated*task do*this*and*do*that*and*another thing @@ -976,7 +976,7 @@ Do not change to a reference style link. Image tags that link to files with a video extension are automatically converted to a video player. The valid video extensions are `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`: -```md +```markdown Here's a sample video: ![Sample Video](img/markdown_video.mp4) @@ -993,7 +993,7 @@ Here's a sample video: Similar to videos, link tags for files with an audio extension are automatically converted to an audio player. The valid audio extensions are `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`: -```md +```markdown Here's a sample audio clip: ![Sample Audio](img/markdown_audio.mp3) @@ -1275,7 +1275,7 @@ number, and count up from there. Examples: -```md +```markdown 1. First ordered list item 2. Another item - Unordered sub-list. @@ -1302,7 +1302,7 @@ See https://docs.gitlab.com/ee/development/documentation/styleguide.html#lists For an unordered list, add a `-`, `*` or `+`, followed by a space, at the start of each line for unordered lists, but you should not use a mix of them. -```md +```markdown Unordered lists can: - use diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md index f7a6858c3cb..154c6e3e52f 100644 --- a/doc/user/packages/container_registry/index.md +++ b/doc/user/packages/container_registry/index.md @@ -137,7 +137,7 @@ The minimum scope needed for both of them is `read_registry`. Example of using a token: -```sh +```shell docker login registry.example.com -u <username> -p <token> ``` @@ -206,7 +206,7 @@ Available for all projects, though more suitable for public ones: your Docker images and has read/write access to the Registry. This is ephemeral, so it's only valid for one job. You can use the following example as-is: - ```sh + ```shell docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY ``` @@ -221,7 +221,7 @@ For private and internal projects: Replace the `<username>` and `<access_token>` in the following example: - ```sh + ```shell docker login -u <username> -p <access_token> $CI_REGISTRY ``` @@ -231,7 +231,7 @@ For private and internal projects: Once created, you can use the special environment variables, and GitLab CI/CD will fill them in for you. You can use the following example as-is: - ```sh + ```shell docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY ``` diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md index a02dc016f03..16ac53a2b52 100644 --- a/doc/user/project/description_templates.md +++ b/doc/user/project/description_templates.md @@ -39,6 +39,26 @@ templates of the default branch will be taken into account. Create a new Markdown (`.md`) file inside the `.gitlab/issue_templates/` directory in your repository. Commit and push to your default branch. +To create a Markdown file: + + 1. Click the `+` button next to `master` and click **New file**. + 1. Add the name of your issue template to the **File name** text field next to `master`. + Make sure words are separated with underscores and that your file has the `.md` extension, for + example `feature_request.md`. + 1. Commit and push to your default branch. + +If you don't have a `.gitlab/issue_templates` directory in your repository, you'll need to create it. + +To create the `.gitlab/issue_templates` directory: + + 1. Click the `+` button next to `master` and select **New directory**. + 1. Name this new directory `.gitlab` and commit to your default branch. + 1. Click the `+` button next to `master` again and select **New directory**.This time, n + 1. Name your directory `issue_templates` and commit to your default branch. + +To check if this has worked correctly, [create a new issue](./issues/managing_issues.md#create-a-new-issue) +and see if you can choose a description template. + ## Creating merge request templates Similarly to issue templates, create a new Markdown (`.md`) file inside the diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index 290e4f81ca3..4e329889e7c 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -183,7 +183,7 @@ but it will not close automatically. If the issue is in a different repository than the MR, add the full URL for the issue(s): -```md +```markdown Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx> ``` diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md index 8ea51514515..3c7a64a38e5 100644 --- a/doc/user/project/releases/index.md +++ b/doc/user/project/releases/index.md @@ -252,6 +252,9 @@ generate Release Evidence for an existing release. Because of this, [each releas can have multiple Release Evidence snapshots. You can view the Release Evidence and its details on the Release page. +NOTE: **Note:** +When the issue tracker is disabled, release evidence [is not collected](https://gitlab.com/gitlab-org/gitlab/-/issues/208397). + Release Evidence is stored as a JSON object, so you can compare evidence by using commonly-available tools. @@ -371,7 +374,7 @@ freeze periods, all will apply, and should they overlap, the freeze covers the complete overlapped period. During pipeline processing, GitLab CI creates an environment variable named -`$CI_ENVIRONMENT_FROZEN` if the currently executing job is within a +`$CI_DEPLOY_FREEZE` if the currently executing job is within a Freeze Period. To take advantage of this variable, create a `rules` entry in your @@ -384,7 +387,7 @@ deploy_to_production: stage: deploy script: deploy_to_prod.sh rules: - - if: $CI_ENVIRONMENT_FROZEN == null + - if: $CI_DEPLOY_FREEZE == null ``` <!-- ## Troubleshooting diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md index 7d377999bc1..20143af0b33 100644 --- a/doc/user/project/repository/x509_signed_commits/index.md +++ b/doc/user/project/repository/x509_signed_commits/index.md @@ -47,7 +47,7 @@ and some of them generate keys for free. To take advantage of X.509 signing, you will need Git 2.19.0 or later. You can check your Git version with: -```sh +```shell git --version ``` @@ -57,7 +57,7 @@ If you have the correct version, you can proceed to configure Git. Configure Git to use your key for signing: -```sh +```shell signingkey = $( gpgsm --list-secret-keys | egrep '(key usage|ID)' | grep -B 1 digitalSignature | awk '/ID/ {print $2}' ) git config --global user.signingkey $signingkey git config --global gpg.format x509 @@ -71,7 +71,7 @@ installer or via `brew install smimesign` on MacOS. Get the ID of your certificate with `smimesign --list-keys` and set your signingkey `git config --global user.signingkey ID`, then configure X.509: -```sh +```shell git config --global gpg.x509.program smimesign git config --global gpg.format x509 ``` @@ -83,7 +83,7 @@ can start signing your commits: 1. Commit like you used to, the only difference is the addition of the `-S` flag: - ```sh + ```shell git commit -S -m "feat: x509 signed commits" ``` @@ -92,7 +92,7 @@ can start signing your commits: If you don't want to type the `-S` flag every time you commit, you can tell Git to sign your commits automatically: -```sh +```shell git config --global commit.gpgsign true ``` @@ -100,7 +100,7 @@ git config --global commit.gpgsign true To verify that a commit is signed, you can use the `--show-signature` flag: -```sh +```shell git log --show-signature ``` @@ -111,7 +111,7 @@ can start signing your tags: 1. Tag like you used to, the only difference is the addition of the `-s` flag: - ```sh + ```shell git tag -s v1.1.1 -m "My signed tag" ``` @@ -120,7 +120,7 @@ can start signing your tags: If you don't want to type the `-s` flag every time you tag, you can tell Git to sign your tags automatically: -```sh +```shell git config --global tag.gpgsign true ``` @@ -128,6 +128,6 @@ git config --global tag.gpgsign true To verify that a tag is signed, you can use the `--verify` flag: -```sh +```shell git tag --verify v1.1.1 ``` diff --git a/spec/controllers/admin/ci/variables_controller_spec.rb b/spec/controllers/admin/ci/variables_controller_spec.rb new file mode 100644 index 00000000000..57f2dd21f39 --- /dev/null +++ b/spec/controllers/admin/ci/variables_controller_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Admin::Ci::VariablesController do + let_it_be(:variable) { create(:ci_instance_variable) } + + before do + sign_in(user) + end + + describe 'GET #show' do + subject do + get :show, params: {}, format: :json + end + + context 'when signed in as admin' do + let(:user) { create(:admin) } + + include_examples 'GET #show lists all variables' + end + + context 'when signed in as regular user' do + let(:user) { create(:user) } + + it 'returns 404' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + describe 'PATCH #update' do + subject do + patch :update, + params: { + variables_attributes: variables_attributes + }, + format: :json + end + + context 'when signed in as admin' do + let(:user) { create(:admin) } + + include_examples 'PATCH #update updates variables' do + let(:variables_scope) { Ci::InstanceVariable.all } + let(:file_variables_scope) { variables_scope.file } + end + end + + context 'when signed in as regular user' do + let(:user) { create(:user) } + + let(:variables_attributes) do + [{ + id: variable.id, + key: variable.key, + secret_value: 'new value' + }] + end + + it 'returns 404' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end +end diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 0d87c27b635..d72fd137f3f 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -111,26 +111,6 @@ RSpec.describe Release do end end - describe '#notify_new_release' do - context 'when a release is created' do - it 'instantiates NewReleaseWorker to send notifications' do - expect(NewReleaseWorker).to receive(:perform_async) - - create(:release) - end - end - - context 'when a release is updated' do - let!(:release) { create(:release) } - - it 'does not send any new notification' do - expect(NewReleaseWorker).not_to receive(:perform_async) - - release.update!(description: 'new description') - end - end - end - describe '#name' do context 'name is nil' do before do diff --git a/spec/services/ci/update_instance_variables_service_spec.rb b/spec/services/ci/update_instance_variables_service_spec.rb new file mode 100644 index 00000000000..93f6e5d3ea8 --- /dev/null +++ b/spec/services/ci/update_instance_variables_service_spec.rb @@ -0,0 +1,230 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::UpdateInstanceVariablesService do + let(:params) { { variables_attributes: variables_attributes } } + + subject { described_class.new(params) } + + describe '#execute' do + context 'without variables' do + let(:variables_attributes) { [] } + + it { expect(subject.execute).to be_truthy } + end + + context 'with insert only variables' do + let(:variables_attributes) do + [ + { key: 'var_a', secret_value: 'dummy_value_for_a', protected: true }, + { key: 'var_b', secret_value: 'dummy_value_for_b', protected: false } + ] + end + + it { expect(subject.execute).to be_truthy } + + it 'persists all the records' do + expect { subject.execute } + .to change { Ci::InstanceVariable.count } + .by variables_attributes.size + end + + it 'persists attributes' do + subject.execute + + expect(Ci::InstanceVariable.all).to contain_exactly( + have_attributes(key: 'var_a', secret_value: 'dummy_value_for_a', protected: true), + have_attributes(key: 'var_b', secret_value: 'dummy_value_for_b', protected: false) + ) + end + end + + context 'with update only variables' do + let!(:var_a) { create(:ci_instance_variable) } + let!(:var_b) { create(:ci_instance_variable, protected: false) } + + let(:variables_attributes) do + [ + { + id: var_a.id, + key: var_a.key, + secret_value: 'new_dummy_value_for_a', + protected: var_a.protected?.to_s + }, + { + id: var_b.id, + key: 'var_b_key', + secret_value: 'new_dummy_value_for_b', + protected: 'true' + } + ] + end + + it { expect(subject.execute).to be_truthy } + + it 'does not change the count' do + expect { subject.execute } + .not_to change { Ci::InstanceVariable.count } + end + + it 'updates the records in place', :aggregate_failures do + subject.execute + + expect(var_a.reload).to have_attributes(secret_value: 'new_dummy_value_for_a') + + expect(var_b.reload).to have_attributes( + key: 'var_b_key', secret_value: 'new_dummy_value_for_b', protected: true) + end + end + + context 'with insert and update variables' do + let!(:var_a) { create(:ci_instance_variable) } + + let(:variables_attributes) do + [ + { + id: var_a.id, + key: var_a.key, + secret_value: 'new_dummy_value_for_a', + protected: var_a.protected?.to_s + }, + { + key: 'var_b', + secret_value: 'dummy_value_for_b', + protected: true + } + ] + end + + it { expect(subject.execute).to be_truthy } + + it 'inserts only one record' do + expect { subject.execute } + .to change { Ci::InstanceVariable.count }.by 1 + end + + it 'persists all the records', :aggregate_failures do + subject.execute + var_b = Ci::InstanceVariable.find_by(key: 'var_b') + + expect(var_a.reload.secret_value).to eq('new_dummy_value_for_a') + expect(var_b.secret_value).to eq('dummy_value_for_b') + end + end + + context 'with insert, update, and destroy variables' do + let!(:var_a) { create(:ci_instance_variable) } + let!(:var_b) { create(:ci_instance_variable) } + + let(:variables_attributes) do + [ + { + id: var_a.id, + key: var_a.key, + secret_value: 'new_dummy_value_for_a', + protected: var_a.protected?.to_s + }, + { + id: var_b.id, + key: var_b.key, + secret_value: 'dummy_value_for_b', + protected: var_b.protected?.to_s, + '_destroy' => 'true' + }, + { + key: 'var_c', + secret_value: 'dummy_value_for_c', + protected: true + } + ] + end + + it { expect(subject.execute).to be_truthy } + + it 'persists all the records', :aggregate_failures do + subject.execute + var_c = Ci::InstanceVariable.find_by(key: 'var_c') + + expect(var_a.reload.secret_value).to eq('new_dummy_value_for_a') + expect { var_b.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect(var_c.secret_value).to eq('dummy_value_for_c') + end + end + + context 'with invalid variables' do + let!(:var_a) { create(:ci_instance_variable, secret_value: 'dummy_value_for_a') } + + let(:variables_attributes) do + [ + { + key: '...?', + secret_value: 'nice_value' + }, + { + id: var_a.id, + key: var_a.key, + secret_value: 'new_dummy_value_for_a', + protected: var_a.protected?.to_s + }, + { + key: var_a.key, + secret_value: 'other_value' + } + ] + end + + it { expect(subject.execute).to be_falsey } + + it 'does not insert any records' do + expect { subject.execute } + .not_to change { Ci::InstanceVariable.count } + end + + it 'does not update existing records' do + subject.execute + + expect(var_a.reload.secret_value).to eq('dummy_value_for_a') + end + + it 'returns errors' do + subject.execute + + expect(subject.errors).to match_array( + [ + "Key (#{var_a.key}) has already been taken", + "Key can contain only letters, digits and '_'." + ]) + end + end + + context 'when deleting non existing variables' do + let(:variables_attributes) do + [ + { + id: 'some-id', + key: 'some_key', + secret_value: 'other_value', + '_destroy' => 'true' + } + ] + end + + it { expect { subject.execute }.to raise_error(ActiveRecord::RecordNotFound) } + end + + context 'when updating non existing variables' do + let(:variables_attributes) do + [ + { + id: 'some-id', + key: 'some_key', + secret_value: 'other_value' + } + ] + end + + it { expect { subject.execute }.to raise_error(ActiveRecord::RecordNotFound) } + end + end +end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 7d6fd9430eb..2a7166e3895 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -762,7 +762,7 @@ describe NotificationService, :mailer do end end - describe '#send_new_release_notifications', :deliver_mails_inline, :sidekiq_inline do + describe '#send_new_release_notifications', :deliver_mails_inline do context 'when recipients for a new release exist' do let(:release) { create(:release) } @@ -774,7 +774,7 @@ describe NotificationService, :mailer do recipient_2 = NotificationRecipient.new(user_2, :custom, custom_action: :new_release) allow(NotificationRecipients::BuildService).to receive(:build_new_release_recipients).and_return([recipient_1, recipient_2]) - release + notification.send_new_release_notifications(release) should_email(user_1) should_email(user_2) diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb index 255f044db90..d0859500440 100644 --- a/spec/services/releases/create_service_spec.rb +++ b/spec/services/releases/create_service_spec.rb @@ -20,6 +20,8 @@ describe Releases::CreateService do describe '#execute' do shared_examples 'a successful release creation' do it 'creates a new release' do + expected_job_count = MailScheduler::NotificationServiceWorker.jobs.size + 1 + result = service.execute expect(project.releases.count).to eq(1) @@ -30,6 +32,7 @@ describe Releases::CreateService do expect(result[:release].name).to eq(name) expect(result[:release].author).to eq(user) expect(result[:release].sha).to eq(tag_sha) + expect(MailScheduler::NotificationServiceWorker.jobs.size).to eq(expected_job_count) end end diff --git a/spec/support/shared_examples/controllers/variables_shared_examples.rb b/spec/support/shared_examples/controllers/variables_shared_examples.rb index 752bdc47851..9ff0bc3d217 100644 --- a/spec/support/shared_examples/controllers/variables_shared_examples.rb +++ b/spec/support/shared_examples/controllers/variables_shared_examples.rb @@ -27,6 +27,9 @@ RSpec.shared_examples 'PATCH #update updates variables' do protected: 'false' } end + let(:variables_scope) { owner.variables } + let(:file_variables_scope) { owner.variables.file } + context 'with invalid new variable parameters' do let(:variables_attributes) do [ @@ -40,7 +43,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do end it 'does not create the new variable' do - expect { subject }.not_to change { owner.variables.count } + expect { subject }.not_to change { variables_scope.count } end it 'returns a bad request response' do @@ -63,7 +66,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do end it 'does not create the new variable' do - expect { subject }.not_to change { owner.variables.count } + expect { subject }.not_to change { variables_scope.count } end it 'returns a bad request response' do @@ -86,7 +89,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do end it 'creates the new variable' do - expect { subject }.to change { owner.variables.count }.by(1) + expect { subject }.to change { variables_scope.count }.by(1) end it 'returns a successful response' do @@ -106,7 +109,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do let(:variables_attributes) { [variable_attributes.merge(_destroy: 'true')] } it 'destroys the variable' do - expect { subject }.to change { owner.variables.count }.by(-1) + expect { subject }.to change { variables_scope.count }.by(-1) expect { variable.reload }.to raise_error ActiveRecord::RecordNotFound end @@ -123,6 +126,18 @@ RSpec.shared_examples 'PATCH #update updates variables' do end end + context 'with missing variable' do + let(:variables_attributes) do + [variable_attributes.merge(_destroy: 'true', id: 'some-id')] + end + + it 'returns not found response' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + context 'for variables of type file' do let(:variables_attributes) do [ @@ -131,7 +146,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do end it 'creates new variable of type file' do - expect { subject }.to change { owner.variables.file.count }.by(1) + expect { subject }.to change { file_variables_scope.count }.by(1) end end end diff --git a/spec/workers/new_release_worker_spec.rb b/spec/workers/new_release_worker_spec.rb index 9d8c5bbf919..de4e1bac48f 100644 --- a/spec/workers/new_release_worker_spec.rb +++ b/spec/workers/new_release_worker_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# TODO: Worker can be removed in 13.2: +# https://gitlab.com/gitlab-org/gitlab/-/issues/218231 require 'spec_helper' describe NewReleaseWorker do |