diff --git a/app/assets/javascripts/static_site_editor/constants.js b/app/assets/javascripts/static_site_editor/constants.js index 4794cf5eead..49ca5907910 100644 --- a/app/assets/javascripts/static_site_editor/constants.js +++ b/app/assets/javascripts/static_site_editor/constants.js @@ -17,3 +17,4 @@ export const LOAD_CONTENT_ERROR = __( export const DEFAULT_HEADING = s__('StaticSiteEditor|Static site editor'); export const TRACKING_ACTION_CREATE_COMMIT = 'create_commit'; +export const TRACKING_ACTION_CREATE_MERGE_REQUEST = 'create_merge_request'; diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js index 49135d2141b..fce7c1f918f 100644 --- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js +++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js @@ -10,6 +10,7 @@ import { SUBMIT_CHANGES_COMMIT_ERROR, SUBMIT_CHANGES_MERGE_REQUEST_ERROR, TRACKING_ACTION_CREATE_COMMIT, + TRACKING_ACTION_CREATE_MERGE_REQUEST, } from '../constants'; const createBranch = (projectId, branch) => @@ -41,8 +42,15 @@ const commitContent = (projectId, message, branch, sourcePath, content) => { }); }; -const createMergeRequest = (projectId, title, sourceBranch, targetBranch = DEFAULT_TARGET_BRANCH) => - Api.createProjectMergeRequest( +const createMergeRequest = ( + projectId, + title, + sourceBranch, + targetBranch = DEFAULT_TARGET_BRANCH, +) => { + Tracking.event(document.body.dataset.page, TRACKING_ACTION_CREATE_MERGE_REQUEST); + + return Api.createProjectMergeRequest( projectId, convertObjectPropsToSnakeCase({ title, @@ -52,6 +60,7 @@ const createMergeRequest = (projectId, title, sourceBranch, targetBranch = DEFAU ).catch(() => { throw new Error(SUBMIT_CHANGES_MERGE_REQUEST_ERROR); }); +}; const submitContentChanges = ({ username, projectId, sourcePath, content }) => { const branch = generateBranchName(username); diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index e93aeba6dfd..c1f343edd10 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -188,7 +188,7 @@ module EventsHelper end def event_wiki_page_target_url(event) - project_wiki_url(event.project, event.target.canonical_slug) + project_wiki_url(event.project, event.target&.canonical_slug || Wiki::HOMEPAGE) end def event_note_title_html(event) diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb index e01c1ab68aa..86c408aeec8 100644 --- a/app/services/projects/alerting/notify_service.rb +++ b/app/services/projects/alerting/notify_service.rb @@ -63,6 +63,8 @@ module Projects end def process_incident_issues(alert) + return if alert.issue + IncidentManagement::ProcessAlertWorker .perform_async(project.id, parsed_payload, alert.id) end diff --git a/app/services/prometheus/create_default_alerts_service.rb b/app/services/prometheus/create_default_alerts_service.rb index c87cbbbe3cf..53baf6a650e 100644 --- a/app/services/prometheus/create_default_alerts_service.rb +++ b/app/services/prometheus/create_default_alerts_service.rb @@ -33,6 +33,7 @@ module Prometheus return ServiceResponse.error(message: 'Invalid environment') unless environment create_alerts + schedule_prometheus_update ServiceResponse.success end @@ -51,6 +52,16 @@ module Prometheus end end + def schedule_prometheus_update + return unless prometheus_application + + ::Clusters::Applications::ScheduleUpdateService.new(prometheus_application, project).execute + end + + def prometheus_application + environment.cluster_prometheus_adapter + end + def metrics_by_identifier strong_memoize(:metrics_by_identifier) do metric_identifiers = DEFAULT_ALERTS.map { |alert| alert[:identifier] } diff --git a/changelogs/unreleased/216678-sse-track-merge-requests.yml b/changelogs/unreleased/216678-sse-track-merge-requests.yml new file mode 100644 index 00000000000..30d3f722b50 --- /dev/null +++ b/changelogs/unreleased/216678-sse-track-merge-requests.yml @@ -0,0 +1,5 @@ +--- +title: Track merge requests submitted by Static Site Editor +merge_request: 34105 +author: +type: added diff --git a/changelogs/unreleased/216735-fix-prometheus-alerts-not-being-created.yml b/changelogs/unreleased/216735-fix-prometheus-alerts-not-being-created.yml new file mode 100644 index 00000000000..cfcd401f6ca --- /dev/null +++ b/changelogs/unreleased/216735-fix-prometheus-alerts-not-being-created.yml @@ -0,0 +1,5 @@ +--- +title: Fix prometheus alerts not being automatically created +merge_request: 33806 +author: +type: fixed diff --git a/changelogs/unreleased/220300-do-not-create-duplicate-alert-issues.yml b/changelogs/unreleased/220300-do-not-create-duplicate-alert-issues.yml new file mode 100644 index 00000000000..e6a8a952561 --- /dev/null +++ b/changelogs/unreleased/220300-do-not-create-duplicate-alert-issues.yml @@ -0,0 +1,5 @@ +--- +title: Do not create duplicate issues for exising Alert Management alerts +merge_request: 33860 +author: +type: fixed diff --git a/changelogs/unreleased/ajk-safe-wiki-event-url.yml b/changelogs/unreleased/ajk-safe-wiki-event-url.yml new file mode 100644 index 00000000000..4e25186e024 --- /dev/null +++ b/changelogs/unreleased/ajk-safe-wiki-event-url.yml @@ -0,0 +1,5 @@ +--- +title: Ensure we always generate a valid wiki event URL +merge_request: 34191 +author: +type: fixed diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 03a45353465..9c0fa783250 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -469,6 +469,11 @@ production: &base geo_file_download_dispatch_worker: cron: "*/1 * * * *" + # GitLab Geo registry sync worker (for backfilling) + # NOTE: This will only take effect if Geo is enabled (secondary nodes only) + geo_registry_sync_worker: + cron: "*/1 * * * *" + # GitLab Geo migrated local files clean up worker # NOTE: This will only take effect if Geo is enabled (secondary nodes only) geo_migrated_local_files_clean_up_worker: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 2699d0984dc..df552e33fd0 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -513,6 +513,9 @@ Gitlab.ee do Settings.cron_jobs['geo_file_download_dispatch_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_file_download_dispatch_worker']['cron'] ||= '*/1 * * * *' Settings.cron_jobs['geo_file_download_dispatch_worker']['job_class'] ||= 'Geo::FileDownloadDispatchWorker' + Settings.cron_jobs['geo_registry_sync_worker'] ||= Settingslogic.new({}) + Settings.cron_jobs['geo_registry_sync_worker']['cron'] ||= '*/1 * * * *' + Settings.cron_jobs['geo_registry_sync_worker']['job_class'] ||= 'Geo::RegistrySyncWorker' Settings.cron_jobs['geo_metrics_update_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_metrics_update_worker']['cron'] ||= '*/1 * * * *' Settings.cron_jobs['geo_metrics_update_worker']['job_class'] ||= 'Geo::MetricsUpdateWorker' diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md index 967f9033f28..26eb99bd55a 100644 --- a/doc/ci/cloud_deployment/index.md +++ b/doc/ci/cloud_deployment/index.md @@ -121,11 +121,11 @@ After you're all set up on AWS ECS, follow these steps: ```yaml include: - - template: Deploy-ECS.gitlab-ci.yml + - template: AWS/Deploy-ECS.gitlab-ci.yml ``` The `Deploy-ECS` template ships with GitLab and is available [on - GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml). + GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml). 1. Commit and push your updated `.gitlab-ci.yml` to your project's repository, and you're done! @@ -138,7 +138,7 @@ After you're all set up on AWS ECS, follow these steps: application. CAUTION: **Warning:** -The [`Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml) +The [`Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml) template includes both the [`Jobs/Build.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml) and [`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) "sub-templates". Do not include these "sub-templates" on their own, and only include the main diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index ea20ad327bb..1befcc4374d 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -29,7 +29,7 @@ The following table describes the version types and their release cadence: | Version type | Description | Cadence | |:-------------|:------------|:--------| -| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 13.0 on May 22, 2020. Subsequent major releases will be scheduled for May 22 each year, by default. | +| Major | For significant changes, or when any backward-incompatible changes are introduced to the public API. | Yearly. The next major release is GitLab 14.0 on May 22, 2021. Subsequent major releases will be scheduled for May 22 each year, by default. | | Minor | For when new backward-compatible functionality is introduced to the public API, a minor feature is introduced, or when a set of smaller features is rolled out. | Monthly on the 22nd. | | Patch | For backward-compatible bug fixes that fix incorrect behavior. See [Patch releases](#patch-releases). | As needed. | diff --git a/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml new file mode 100644 index 00000000000..82b2f5c035e --- /dev/null +++ b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml @@ -0,0 +1,13 @@ +stages: + - build + - test + - review + - deploy + - production + +variables: + AUTO_DEVOPS_PLATFORM_TARGET: ECS + +include: + - template: Jobs/Build.gitlab-ci.yml + - template: Jobs/Deploy/ECS.gitlab-ci.yml diff --git a/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml index 82b2f5c035e..5f4bd631db6 100644 --- a/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Deploy-ECS.gitlab-ci.yml @@ -1,3 +1,18 @@ +# This template is deprecated and will be removed as part of GitLab 13.2! +# +# If you have referenced this template in your CI pipeline, please +# update your CI configuration by replacing the following occurrence(s): +# +# template: Deploy-ECS.gitlab-ci.yml +# +# with +# +# template: AWS/Deploy-ECS.gitlab-ci.yml +# +# -------------------- +# +# Documentation: https://docs.gitlab.com/ee/ci/cloud_deployment/#deploy-your-application-to-the-aws-elastic-container-service-ecs + stages: - build - test @@ -5,6 +20,9 @@ stages: - deploy - production +before_script: + - printf '\nWARNING!\nThis job includes "Deploy-ECS.gitlab-ci.yml". Please rename this to "AWS/Deploy-ECS.gitlab-ci.yml".\n' + variables: AUTO_DEVOPS_PLATFORM_TARGET: ECS diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb index 9e052f442e7..7d0aaa45e40 100644 --- a/spec/factories/clusters/clusters.rb +++ b/spec/factories/clusters/clusters.rb @@ -86,6 +86,10 @@ FactoryBot.define do application_helm factory: %i(clusters_applications_helm installed) end + trait :with_installed_prometheus do + application_prometheus factory: %i(clusters_applications_prometheus installed) + end + trait :with_all_applications do application_helm factory: %i(clusters_applications_helm installed) application_ingress factory: %i(clusters_applications_ingress installed) diff --git a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js index a1e9ff4ec4c..3636de3fe70 100644 --- a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js +++ b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js @@ -8,6 +8,7 @@ import { SUBMIT_CHANGES_COMMIT_ERROR, SUBMIT_CHANGES_MERGE_REQUEST_ERROR, TRACKING_ACTION_CREATE_COMMIT, + TRACKING_ACTION_CREATE_MERGE_REQUEST, } from '~/static_site_editor/constants'; import generateBranchName from '~/static_site_editor/services/generate_branch_name'; import submitContentChanges from '~/static_site_editor/services/submit_content_changes'; @@ -83,15 +84,6 @@ describe('submitContentChanges', () => { }); }); - it('sends the correct tracking event when committing content changes', () => { - return submitContentChanges({ username, projectId, sourcePath, content }).then(() => { - expect(trackingSpy).toHaveBeenCalledWith( - document.body.dataset.page, - TRACKING_ACTION_CREATE_COMMIT, - ); - }); - }); - it('notifies error when content could not be committed', () => { Api.commitMultiple.mockRejectedValueOnce(); @@ -152,4 +144,24 @@ describe('submitContentChanges', () => { }); }); }); + + describe('sends the correct tracking event', () => { + beforeEach(() => { + return submitContentChanges({ username, projectId, sourcePath, content }); + }); + + it('for committing changes', () => { + expect(trackingSpy).toHaveBeenCalledWith( + document.body.dataset.page, + TRACKING_ACTION_CREATE_COMMIT, + ); + }); + + it('for creating a merge request', () => { + expect(trackingSpy).toHaveBeenCalledWith( + document.body.dataset.page, + TRACKING_ACTION_CREATE_MERGE_REQUEST, + ); + }); + }); }); diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb index 12519390137..6f24308757d 100644 --- a/spec/helpers/events_helper_spec.rb +++ b/spec/helpers/events_helper_spec.rb @@ -150,6 +150,21 @@ describe EventsHelper do expect(helper.event_wiki_page_target_url(event)).to eq(url) end + + context 'there is no canonical slug' do + let(:event) { create(:wiki_page_event, project: project) } + + before do + event.target.slugs.update_all(canonical: false) + event.target.clear_memoization(:canonical_slug) + end + + it 'links to the home page' do + url = helper.project_wiki_url(project, Wiki::HOMEPAGE) + + expect(helper.event_wiki_page_target_url(event)).to eq(url) + end + end end describe '#event_wiki_title_html' do diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb index 9d39585b839..22726d5b0ba 100644 --- a/spec/services/projects/alerting/notify_service_spec.rb +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -11,23 +11,18 @@ describe Projects::Alerting::NotifyService do allow(ProjectServiceWorker).to receive(:perform_async) end - shared_examples 'processes incident issues' do |amount| + shared_examples 'processes incident issues' do let(:create_incident_service) { spy } - let(:new_alert) { instance_double(AlertManagement::Alert, id: 503, persisted?: true) } before do - allow(new_alert).to receive(:execute_services) + allow_any_instance_of(AlertManagement::Alert).to receive(:execute_services) end it 'processes issues' do - expect(AlertManagement::Alert) - .to receive(:create) - .and_return(new_alert) - expect(IncidentManagement::ProcessAlertWorker) .to receive(:perform_async) - .with(project.id, kind_of(Hash), new_alert.id) - .exactly(amount).times + .with(project.id, kind_of(Hash), kind_of(Integer)) + .once Sidekiq::Testing.inline! do expect(subject).to be_success @@ -163,7 +158,8 @@ describe Projects::Alerting::NotifyService do end context 'existing alert with same fingerprint' do - let!(:existing_alert) { create(:alert_management_alert, project: project, fingerprint: Digest::SHA1.hexdigest(fingerprint)) } + let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) } + let!(:existing_alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) } it 'does not create AlertManagement::Alert' do expect { subject }.not_to change(AlertManagement::Alert, :count) @@ -220,7 +216,7 @@ describe Projects::Alerting::NotifyService do context 'issue enabled' do let(:issue_enabled) { true } - it_behaves_like 'processes incident issues', 1 + it_behaves_like 'processes incident issues' context 'with an invalid payload' do before do @@ -232,6 +228,21 @@ describe Projects::Alerting::NotifyService do it_behaves_like 'does not process incident issues due to error', http_status: :bad_request it_behaves_like 'NotifyService does not create alert' end + + context 'when alert already exists' do + let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) } + let!(:existing_alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) } + + context 'when existing alert does not have an associated issue' do + it_behaves_like 'processes incident issues' + end + + context 'when existing alert has an associated issue' do + let!(:existing_alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) } + + it_behaves_like 'does not process incident issues' + end + end end context 'with emails turned on' do diff --git a/spec/services/prometheus/create_default_alerts_service_spec.rb b/spec/services/prometheus/create_default_alerts_service_spec.rb index 3382844c99a..a28c38491de 100644 --- a/spec/services/prometheus/create_default_alerts_service_spec.rb +++ b/spec/services/prometheus/create_default_alerts_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Prometheus::CreateDefaultAlertsService do - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, :repository) } let(:instance) { described_class.new(project: project) } let(:expected_alerts) { described_class::DEFAULT_ALERTS } @@ -45,6 +45,23 @@ describe Prometheus::CreateDefaultAlertsService do .by(expected_alerts.size) end + it 'does not schedule an update to prometheus' do + expect(::Clusters::Applications::ScheduleUpdateService).not_to receive(:new) + execute + end + + context 'cluster with prometheus exists' do + let!(:cluster) { create(:cluster, :with_installed_prometheus, :provided_by_user, projects: [project]) } + + it 'schedules an update to prometheus' do + expect_next_instance_of(::Clusters::Applications::ScheduleUpdateService) do |instance| + expect(instance).to receive(:execute) + end + + execute + end + end + context 'multiple environments' do let!(:production) { create(:environment, project: project, name: 'production') }