Commit 101e7e04 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents e3b2cac1 2bd808a1
...@@ -139,10 +139,7 @@ module Projects ...@@ -139,10 +139,7 @@ module Projects
destroy_web_hooks! destroy_web_hooks!
destroy_project_bots! destroy_project_bots!
destroy_ci_records! destroy_ci_records!
destroy_mr_diff_commits!
if ::Feature.enabled?(:extract_mr_diff_commit_deletions, default_enabled: :yaml)
destroy_mr_diff_commits!
end
# Rails attempts to load all related records into memory before # Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510 # destroying: https://github.com/rails/rails/issues/22510
......
---
name: extract_mr_diff_commit_deletions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75963
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347073
milestone: '14.6'
type: development
group: group::code review
default_enabled: false
...@@ -256,7 +256,7 @@ expiration date without a gap in available service. An invoice is ...@@ -256,7 +256,7 @@ expiration date without a gap in available service. An invoice is
generated for the renewal and available for viewing or download on the generated for the renewal and available for viewing or download on the
[View invoices](https://customers.gitlab.com/receipts) page. [View invoices](https://customers.gitlab.com/receipts) page.
#### Enable automatic renewal #### Enable or disable automatic renewal
To view or change automatic subscription renewal (at the same tier as the To view or change automatic subscription renewal (at the same tier as the
previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and: previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
...@@ -292,7 +292,7 @@ for more information. ...@@ -292,7 +292,7 @@ for more information.
### Purchase additional CI/CD minutes ### Purchase additional CI/CD minutes
You can [purchase additional minutes](../../ci/pipelines/cicd_minutes.md#purchase-additional-cicd-minutes) You can [purchase additional minutes](../../ci/pipelines/cicd_minutes.md#purchase-additional-cicd-minutes)
for your personal or group namespace. for your personal or group namespace. CI/CD minutes are a **one-time purchase**, so they do not renew.
## Add-on subscription for additional Storage and Transfer ## Add-on subscription for additional Storage and Transfer
...@@ -309,7 +309,11 @@ locked. Projects can only be unlocked by purchasing more storage subscription un ...@@ -309,7 +309,11 @@ locked. Projects can only be unlocked by purchasing more storage subscription un
### Purchase more storage and transfer ### Purchase more storage and transfer
You can purchase storage for your personal or group namespace. You can purchase a storage subscription for your personal or group namespace.
NOTE:
Storage subscriptions **[renew automatically](#automatic-renewal) each year**.
You can [cancel the subscription](#enable-or-disable-automatic-renewal) to disable the automatic renewal.
#### For your personal namespace #### For your personal namespace
......
...@@ -10,10 +10,19 @@ module Gitlab ...@@ -10,10 +10,19 @@ module Gitlab
Result = Struct.new(:cmd, :stdout, :stderr, :status, :duration) Result = Struct.new(:cmd, :stdout, :stderr, :status, :duration)
# Returns [stdout + stderr, status] # Returns [stdout + stderr, status]
# status is either the exit code or the signal that killed the process
def popen(cmd, path = nil, vars = {}, &block) def popen(cmd, path = nil, vars = {}, &block)
result = popen_with_detail(cmd, path, vars, &block) result = popen_with_detail(cmd, path, vars, &block)
["#{result.stdout}#{result.stderr}", result.status&.exitstatus] # Process#waitpid returns Process::Status, which holds a 16-bit value.
# The higher-order 8 bits hold the exit() code (`exitstatus`).
# The lower-order bits holds whether the process was terminated.
# If the process didn't exit normally, `exitstatus` will be `nil`,
# but we still want a non-zero code, even if the value is
# platform-dependent.
status = result.status&.exitstatus || result.status.to_i
["#{result.stdout}#{result.stderr}", status]
end end
# Returns Result # Returns Result
......
...@@ -40,6 +40,17 @@ RSpec.describe Gitlab::Popen do ...@@ -40,6 +40,17 @@ RSpec.describe Gitlab::Popen do
it { expect(@output).to include('No such file or directory') } it { expect(@output).to include('No such file or directory') }
end end
context 'non-zero status with a kill' do
let(:cmd) { [Gem.ruby, "-e", "thr = Thread.new { sleep 5 }; Process.kill(9, Process.pid); thr.join"] }
before do
@output, @status = @klass.new.popen(cmd)
end
it { expect(@status).to eq(9) }
it { expect(@output).to be_empty }
end
context 'unsafe string command' do context 'unsafe string command' do
it 'raises an error when it gets called with a string argument' do it 'raises an error when it gets called with a string argument' do
expect { @klass.new.popen('ls', path) }.to raise_error(RuntimeError) expect { @klass.new.popen('ls', path) }.to raise_error(RuntimeError)
......
...@@ -97,9 +97,13 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do ...@@ -97,9 +97,13 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end end
end end
shared_examples_for "deleting a project with merge requests" do context "deleting a project with merge requests" do
let!(:merge_request) { create(:merge_request, source_project: project) } let!(:merge_request) { create(:merge_request, source_project: project) }
before do
allow(project).to receive(:destroy!).and_return(true)
end
it "deletes merge request and related records" do it "deletes merge request and related records" do
merge_request_diffs = merge_request.merge_request_diffs merge_request_diffs = merge_request.merge_request_diffs
expect(merge_request_diffs.size).to eq(1) expect(merge_request_diffs.size).to eq(1)
...@@ -119,25 +123,6 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do ...@@ -119,25 +123,6 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
destroy_project(project, user, {}) destroy_project(project, user, {})
end end
context "extract_mr_diff_commit_deletions feature flag" do
context "with flag enabled" do
before do
stub_feature_flags(extract_mr_diff_commit_deletions: true)
allow(project).to receive(:destroy!).and_return(true)
end
it_behaves_like "deleting a project with merge requests"
end
context "with flag disabled" do
before do
stub_feature_flags(extract_mr_diff_commit_deletions: false)
end
it_behaves_like "deleting a project with merge requests"
end
end
context 'with running pipelines' do context 'with running pipelines' do
let!(:pipelines) { create_list(:ci_pipeline, 3, :running, project: project) } let!(:pipelines) { create_list(:ci_pipeline, 3, :running, project: project) }
let(:destroy_pipeline_service) { double('DestroyPipelineService', execute: nil) } let(:destroy_pipeline_service) { double('DestroyPipelineService', execute: nil) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment