diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 0108366cc32..44c05389248 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -678,7 +678,7 @@ lib/gitlab/checks/
/doc/administration/settings/account_and_limit_settings.md @brendan777
/doc/administration/settings/continuous_integration.md @lyspin
/doc/administration/settings/deprecated_api_rate_limits.md @brendan777
-/doc/administration/settings/editor_extensions.md @aqualls
+/doc/administration/settings/editor_extensions.md @scawood
/doc/administration/settings/email.md @msedlakjakubowski
/doc/administration/settings/external_authorization.md @idurham
/doc/administration/settings/files_api_rate_limits.md @brendan777
@@ -733,7 +733,7 @@ lib/gitlab/checks/
/doc/api/branches.md @brendan777
/doc/api/bulk_imports.md @ashrafkhamis
/doc/api/chat.md @jglassman1
-/doc/api/code_suggestions.md @jglassman1
+/doc/api/code_suggestions.md @scawood
/doc/api/commits.md @brendan777
/doc/api/compliance_policy_settings.md @rlehmann1
/doc/api/container_registry.md @z_painter
@@ -991,7 +991,8 @@ lib/gitlab/checks/
/doc/development/stage_group_observability/ @gitlab-org/analytics-section/product-analytics/engineers/frontend
/doc/development/tracing.md @gitlab-org/analytics-section/product-analytics/engineers/frontend
/doc/drawers/ @ashrafkhamis
-/doc/editor_extensions/ @aqualls
+/doc/editor_extensions/ @scawood
+/doc/editor_extensions/gitlab_cli/ @aqualls
/doc/install/ @axil @eread
/doc/install/install_ai_gateway.md @sselhorn
/doc/integration/ @idurham
@@ -1193,7 +1194,7 @@ lib/gitlab/checks/
/doc/user/project/merge_requests/ @aqualls
/doc/user/project/merge_requests/approvals/ @brendan777
/doc/user/project/merge_requests/cherry_pick_changes.md @brendan777
-/doc/user/project/merge_requests/duo_in_merge_requests.md @jglassman1
+/doc/user/project/merge_requests/duo_in_merge_requests.md @scawood
/doc/user/project/merge_requests/methods/ @brendan777
/doc/user/project/merge_requests/squash_and_merge.md @brendan777
/doc/user/project/merge_requests/status_checks.md @rlehmann1
@@ -1206,8 +1207,8 @@ lib/gitlab/checks/
/doc/user/project/releases/ @eread
/doc/user/project/remote_development/ @brendan777
/doc/user/project/repository/ @brendan777
-/doc/user/project/repository/code_explain.md @jglassman1
-/doc/user/project/repository/code_suggestions/ @jglassman1
+/doc/user/project/repository/code_explain.md @scawood
+/doc/user/project/repository/code_suggestions/ @scawood
/doc/user/project/repository/monorepos/ @eread
/doc/user/project/requirements/ @msedlakjakubowski
/doc/user/project/service_desk/ @msedlakjakubowski
diff --git a/.gitlab/ci/release-environments/security.gitlab-ci.yml b/.gitlab/ci/release-environments/security.gitlab-ci.yml
index fd40baad72e..dbb45744168 100644
--- a/.gitlab/ci/release-environments/security.gitlab-ci.yml
+++ b/.gitlab/ci/release-environments/security.gitlab-ci.yml
@@ -56,7 +56,7 @@ release-environments-build-omnibus-env:
- for version_file in *_VERSION; do echo "$version_file=$(cat $version_file)" >> $BUILD_ENV; done
- ruby -e 'puts "FULL_RUBY_VERSION=#{RUBY_VERSION}"' >> $BUILD_ENV
- echo "SHORT_RUBY_VERSION=${RUBY_VERSION}" >> $BUILD_ENV
- - echo "GITLAB_ASSETS_TAG=$(GLCI_ASSETS_IMAGE_TAG)" >> $BUILD_ENV
+ - echo "GITLAB_ASSETS_TAG=${GLCI_ASSETS_IMAGE_TAG}" >> $BUILD_ENV
- echo "EE=$([[ $FOSS_ONLY == '1' ]] && echo 'false' || echo 'true')" >> $BUILD_ENV
- define_trigger_branch_in_build_env
- echo "Built environment file for omnibus build:"
diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml
index 88429163036..ca33a6a647d 100644
--- a/.gitlab/ci/static-analysis.gitlab-ci.yml
+++ b/.gitlab/ci/static-analysis.gitlab-ci.yml
@@ -332,7 +332,7 @@ ping-appsec-for-dependency-review:
variables:
GIT_CHECKOUT: "false"
DISABLE_MENTIONS: "false"
- DISABLE_SCORING: "true"
+ DISABLE_SCORING: "false"
DISABLE_COMMENTING: "false"
DEPENDENCY_REVIEW_BOT_CI_REG: "${CI_REGISTRY}/gitlab-com/gl-security/product-security/appsec/tooling/depscore/master"
extends: [".ping-appsec-for-dependency-review:rules", ".use-docker-in-docker"]
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index cdc6817b490..8988e0f1e94 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-835b8a2a7a181988190005711222666d1d27b921
+311c173844ce85e28e51818063bcac8e75dee41e
diff --git a/app/assets/javascripts/ide/lib/gitlab_web_ide/handle_update_url.js b/app/assets/javascripts/ide/lib/gitlab_web_ide/handle_update_url.js
index c27d658ce92..d3cc119f95f 100644
--- a/app/assets/javascripts/ide/lib/gitlab_web_ide/handle_update_url.js
+++ b/app/assets/javascripts/ide/lib/gitlab_web_ide/handle_update_url.js
@@ -1,28 +1,12 @@
import { joinPaths, webIDEUrl } from '~/lib/utils/url_utility';
-function withPrevious(fn) {
- let prev;
-
- return (arg) => {
- fn(arg, prev);
- prev = arg;
- };
-}
-
function getWebIdeUrl(projectPath, branchName) {
return webIDEUrl(joinPaths('/', projectPath, 'edit', branchName, '-/'));
}
-export const handleUpdateUrl = withPrevious(({ projectPath, ref }, previous) => {
- if (!previous) {
- return;
- }
-
- if (previous.ref === ref) {
- return;
- }
-
+export const handleUpdateUrl = ({ projectPath, ref }) => {
const newUrl = getWebIdeUrl(projectPath, ref);
window.history.replaceState(null, '', newUrl);
-});
+ window.location.reload();
+};
diff --git a/app/assets/javascripts/members/placeholders/components/app.vue b/app/assets/javascripts/members/placeholders/components/app.vue
index f12d603cdae..074dbbd8182 100644
--- a/app/assets/javascripts/members/placeholders/components/app.vue
+++ b/app/assets/javascripts/members/placeholders/components/app.vue
@@ -2,6 +2,7 @@
// eslint-disable-next-line no-restricted-imports
import { mapState } from 'vuex';
import {
+ GlTooltipDirective,
GlBadge,
GlTab,
GlTabs,
@@ -76,6 +77,7 @@ export default {
KeepAllAsPlaceholderModal,
},
directives: {
+ GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
},
inject: {
@@ -421,7 +423,6 @@ export default {
@@ -429,11 +430,12 @@ export default {
e
log(:error, "Failed to add failure issue link for example '#{example.description}', error: #{e}")
diff --git a/qa/spec/support/formatters/allure_metadata_formatter_spec.rb b/qa/spec/support/formatters/allure_metadata_formatter_spec.rb
index 80ad3ccc029..57935004bd6 100644
--- a/qa/spec/support/formatters/allure_metadata_formatter_spec.rb
+++ b/qa/spec/support/formatters/allure_metadata_formatter_spec.rb
@@ -13,7 +13,7 @@ describe QA::Support::Formatters::AllureMetadataFormatter do
)
end
- # rubocop:disable RSpec/VerifiedDoubles
+ # rubocop:disable RSpec/VerifiedDoubles -- verified double complains about missing dynamically added methods
let(:rspec_example) do
double(
RSpec::Core::Example,
@@ -52,7 +52,7 @@ describe QA::Support::Formatters::AllureMetadataFormatter do
expect(rspec_example).to have_received(:add_link).with(name: "Job(#{ci_job})", url: ci_job_url)
expect(rspec_example).to have_received(:issue).with(
'Failure issues',
- 'https://gitlab.com/gitlab-org/gitlab/-/issues?sort=updated_desc&scope=all&state=opened&' \
+ 'https://gitlab.com/gitlab-org/quality/e2e-test-issues/-/issues?sort=updated_desc&scope=all&state=opened&' \
'search=spec.rb&search=Some%20failure%0Amessage'
)
end
@@ -71,7 +71,7 @@ describe QA::Support::Formatters::AllureMetadataFormatter do
expect(rspec_example).to have_received(:issue).with(
'Failure issues',
- 'https://gitlab.com/gitlab-org/gitlab/-/issues?sort=updated_desc&scope=all&state=opened&' \
+ 'https://gitlab.com/gitlab-org/quality/e2e-test-issues/-/issues?sort=updated_desc&scope=all&state=opened&' \
'search=spec.rb&search=Some%20failure%20message'
)
end
diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb
index 4b8f1f47c4d..14828e41db5 100644
--- a/spec/channels/application_cable/connection_spec.rb
+++ b/spec/channels/application_cable/connection_spec.rb
@@ -147,4 +147,24 @@ RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do
expect(connection.current_user).to be_nil
end
end
+
+ describe 'setting current organization' do
+ let(:organization) { create(:organization) }
+
+ before do
+ allow_next_instance_of(Gitlab::Current::Organization) do |instance|
+ allow(instance).to receive(:organization).and_return(organization)
+ end
+ end
+
+ it 'sets current_organization' do
+ expect(Gitlab::Current::Organization).to receive(:new).with(
+ params: connection.request.params, user: connection.current_user
+ )
+
+ connect
+
+ expect(connection.current_organization).to eq(organization)
+ end
+ end
end
diff --git a/spec/frontend/ide/lib/gitlab_web_ide/handle_update_url_spec.js b/spec/frontend/ide/lib/gitlab_web_ide/handle_update_url_spec.js
index de2369ec619..2237cb499b1 100644
--- a/spec/frontend/ide/lib/gitlab_web_ide/handle_update_url_spec.js
+++ b/spec/frontend/ide/lib/gitlab_web_ide/handle_update_url_spec.js
@@ -3,56 +3,41 @@ import { handleUpdateUrl } from '~/ide/lib/gitlab_web_ide/handle_update_url';
const MOCK_PROJECT_NAME = 'project-path';
const MOCK_BRANCH_NAME = 'branch';
const RELATIVE_URL_ROOT = '/gitlab';
+const WINDOW_RELOAD = window.location.reload;
describe('ide/handle_update_url', () => {
+ beforeAll(() => {
+ Object.defineProperty(window, 'location', {
+ value: { reload: jest.fn() },
+ });
+ });
beforeEach(() => {
window.gon.relative_url_root = '';
});
- it('does not update the url if no previous state stored', () => {
+ afterAll(() => {
+ window.location.reload = WINDOW_RELOAD;
+ });
+
+ it('updates the URL and reloads the page', () => {
+ const historySpy = jest.spyOn(window.history, 'replaceState');
+ const locationSpy = jest.spyOn(window.location, 'reload');
+ handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: MOCK_BRANCH_NAME });
+
+ expect(historySpy).toHaveBeenCalledTimes(1);
+ expect(locationSpy).toHaveBeenCalledTimes(1);
+ });
+
+ it('includes the relative url root if it exists', () => {
+ window.gon.relative_url_root = RELATIVE_URL_ROOT;
const historySpy = jest.spyOn(window.history, 'replaceState');
handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: MOCK_BRANCH_NAME });
- expect(historySpy).toHaveBeenCalledTimes(0);
- });
-
- it('does not update the url if ref did not change', () => {
- window.history.replaceState({ previousRef: MOCK_BRANCH_NAME }, '');
-
- const historySpy = jest.spyOn(window.history, 'replaceState');
- handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: MOCK_BRANCH_NAME });
-
- expect(historySpy).toHaveBeenCalledTimes(0);
- });
-
- describe('when the ref changes', () => {
- beforeEach(() => {
- handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: 'some-ref' });
- });
-
- it('updates the url', () => {
- const historySpy = jest.spyOn(window.history, 'replaceState');
- handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: MOCK_BRANCH_NAME });
-
- expect(historySpy).toHaveBeenCalledTimes(1);
- expect(historySpy).toHaveBeenCalledWith(
- null,
- '',
- `/-/ide/project/${MOCK_PROJECT_NAME}/edit/${MOCK_BRANCH_NAME}/-/`,
- );
- });
-
- it('includes the relative url root if it exists', () => {
- window.gon.relative_url_root = RELATIVE_URL_ROOT;
- const historySpy = jest.spyOn(window.history, 'replaceState');
- handleUpdateUrl({ projectPath: MOCK_PROJECT_NAME, ref: MOCK_BRANCH_NAME });
-
- expect(historySpy).toHaveBeenCalledTimes(1);
- expect(historySpy).toHaveBeenCalledWith(
- null,
- '',
- `${RELATIVE_URL_ROOT}/-/ide/project/${MOCK_PROJECT_NAME}/edit/${MOCK_BRANCH_NAME}/-/`,
- );
- });
+ expect(historySpy).toHaveBeenCalledTimes(1);
+ expect(historySpy).toHaveBeenCalledWith(
+ null,
+ '',
+ `${RELATIVE_URL_ROOT}/-/ide/project/${MOCK_PROJECT_NAME}/edit/${MOCK_BRANCH_NAME}/-/`,
+ );
});
});
diff --git a/spec/lib/gem_extensions/active_record/connection_adapters/transaction/null_transaction_callbacks_spec.rb b/spec/lib/gem_extensions/active_record/connection_adapters/transaction/null_transaction_callbacks_spec.rb
new file mode 100644
index 00000000000..b7175e3c7fe
--- /dev/null
+++ b/spec/lib/gem_extensions/active_record/connection_adapters/transaction/null_transaction_callbacks_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GemExtensions::ActiveRecord::ConnectionAdapters::Transaction::NullTransactionCallbacks, feature_category: :shared do
+ describe '.after_commit' do
+ let(:collection) { [] }
+ let(:current_transaction) { ActiveRecord::ConnectionAdapters::NullTransaction.new }
+
+ subject(:unit_of_work) do
+ current_transaction.after_commit do
+ collection << :after_commit
+ end
+
+ collection << :not_after_commit
+ end
+
+ it 'executes the given block immediately as there is no real transaction' do
+ unit_of_work
+
+ expect(collection).to eq([:after_commit, :not_after_commit])
+ end
+ end
+end
diff --git a/spec/lib/gem_extensions/active_record/connection_adapters/transaction/transaction_callbacks_spec.rb b/spec/lib/gem_extensions/active_record/connection_adapters/transaction/transaction_callbacks_spec.rb
new file mode 100644
index 00000000000..ec07184b3ba
--- /dev/null
+++ b/spec/lib/gem_extensions/active_record/connection_adapters/transaction/transaction_callbacks_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GemExtensions::ActiveRecord::ConnectionAdapters::Transaction::TransactionCallbacks, feature_category: :shared do
+ describe '.after_commit' do
+ let(:collection) { [] }
+
+ context 'with real transaction' do
+ subject(:unit_of_work) do
+ ApplicationRecord.transaction do
+ ApplicationRecord.current_transaction.after_commit do
+ collection << :after_commit
+ end
+
+ collection << :before_commit
+ end
+ end
+
+ it 'executes the given block after the transaction commits' do
+ unit_of_work
+
+ expect(collection).to eq([:before_commit, :after_commit])
+ end
+ end
+
+ context 'with savepoints' do
+ context 'with joinable parent' do
+ subject(:unit_of_work) do
+ ApplicationRecord.transaction do
+ ApplicationRecord.transaction(requires_new: requires_new) do
+ ApplicationRecord.current_transaction.after_commit do
+ collection << :after_commit
+ end
+
+ collection << :before_release
+ end
+
+ collection << :before_commit
+ end
+ end
+
+ context 'with `requires_new: true`' do
+ let(:requires_new) { true }
+
+ it 'executes the given block after the transaction commits' do
+ unit_of_work
+
+ expect(collection).to eq([:before_release, :before_commit, :after_commit])
+ end
+ end
+
+ context 'with `requires_new: false`' do
+ let(:requires_new) { false }
+
+ it 'executes the given block after the transaction commits' do
+ unit_of_work
+
+ expect(collection).to eq([:before_release, :before_commit, :after_commit])
+ end
+ end
+ end
+
+ context 'without joinable parent' do
+ subject(:unit_of_work) do
+ ApplicationRecord.transaction(joinable: false) do
+ ApplicationRecord.transaction(requires_new: requires_new) do
+ ApplicationRecord.current_transaction.after_commit do
+ collection << :after_commit
+ end
+
+ collection << :before_release
+ end
+
+ collection << :before_commit
+ end
+ end
+
+ context 'with `requires_new: true`' do
+ let(:requires_new) { true }
+
+ it 'executes the given block after the transaction commits' do
+ unit_of_work
+
+ expect(collection).to eq([:before_release, :after_commit, :before_commit])
+ end
+ end
+
+ context 'with `requires_new: false`' do
+ let(:requires_new) { false }
+
+ it 'executes the given block after the transaction commits' do
+ unit_of_work
+
+ expect(collection).to eq([:before_release, :after_commit, :before_commit])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 72ed150d929..254e4c9819e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1492,10 +1492,10 @@
dependencies:
"@vue/devtools-api" "^6.0.0-beta.11"
-"@gitlab/web-ide@^0.0.1-dev-20250625063230":
- version "0.0.1-dev-20250625063230"
- resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20250625063230.tgz#ec6c72716c0dd688898f5037f63ac253ad6924f5"
- integrity sha512-pvKeWRuZb4LSXkbUYEmxvQ3Nony9s8CHNY9XywEgEQs49upUPzmfSLl6tftQVs3pKsq2KK8AokR8DJ6bD1Egvg==
+"@gitlab/web-ide@^0.0.1-dev-20250703083336":
+ version "0.0.1-dev-20250703083336"
+ resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20250703083336.tgz#eb6d15b07e940acd32131a2e8b30f9e34a2e7dcb"
+ integrity sha512-HrdwvYj4eAxSPOEbBfsln77qvWdOelkjlYGYV1z+59ldlHcqDjNjwADYAPpRSXfwse1i4mOTb1S61SXDDH0Icg==
"@gleam-lang/highlight.js-gleam@^1.5.0":
version "1.5.0"