Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2947190073
commit
ba2345d720
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import updateMixin from '../mixins/update';
|
||||
import eventHub from '../event_hub';
|
||||
|
@ -10,6 +10,9 @@ const issuableTypes = {
|
|||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
},
|
||||
mixins: [updateMixin],
|
||||
props: {
|
||||
canDestroy: {
|
||||
|
@ -64,28 +67,30 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="gl-mt-3 gl-mb-3 clearfix">
|
||||
<button
|
||||
:class="{ disabled: formState.updateLoading || !isSubmitEnabled }"
|
||||
<gl-button
|
||||
:loading="formState.updateLoading"
|
||||
:disabled="formState.updateLoading || !isSubmitEnabled"
|
||||
class="btn btn-success float-left qa-save-button"
|
||||
category="primary"
|
||||
variant="success"
|
||||
class="float-left qa-save-button"
|
||||
type="submit"
|
||||
@click.prevent="updateIssuable"
|
||||
>
|
||||
Save changes
|
||||
<i v-if="formState.updateLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
|
||||
</button>
|
||||
<button class="btn btn-default float-right" type="button" @click="closeForm">
|
||||
{{ __('Save changes') }}
|
||||
</gl-button>
|
||||
<gl-button class="float-right" @click="closeForm">
|
||||
{{ __('Cancel') }}
|
||||
</button>
|
||||
<button
|
||||
</gl-button>
|
||||
<gl-button
|
||||
v-if="shouldShowDeleteButton"
|
||||
:class="{ disabled: deleteLoading }"
|
||||
:loading="deleteLoading"
|
||||
:disabled="deleteLoading"
|
||||
class="btn btn-danger float-right gl-mr-3 qa-delete-button"
|
||||
type="button"
|
||||
category="primary"
|
||||
variant="danger"
|
||||
class="float-right gl-mr-3 qa-delete-button"
|
||||
@click="deleteIssuable"
|
||||
>
|
||||
Delete <i v-if="deleteLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
|
||||
</button>
|
||||
{{ __('Delete') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
module Ci
|
||||
class BuildTraceChunk < ApplicationRecord
|
||||
include FastDestroyAll
|
||||
extend ::Gitlab::Ci::Model
|
||||
include ::FastDestroyAll
|
||||
include ::Checksummable
|
||||
include ::Gitlab::ExclusiveLeaseHelpers
|
||||
extend Gitlab::Ci::Model
|
||||
|
||||
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
|
||||
|
||||
|
@ -60,8 +61,6 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Data is memoized for optimizing #size and #end_offset
|
||||
def data
|
||||
@data ||= get_data.to_s
|
||||
end
|
||||
|
@ -80,11 +79,11 @@ module Ci
|
|||
|
||||
in_lock(*lock_params) { unsafe_append_data!(new_data, offset) }
|
||||
|
||||
schedule_to_persist if full?
|
||||
schedule_to_persist! if full?
|
||||
end
|
||||
|
||||
def size
|
||||
@size ||= current_store.size(self) || data&.bytesize
|
||||
@size ||= @data&.bytesize || current_store.size(self) || data&.bytesize
|
||||
end
|
||||
|
||||
def start_offset
|
||||
|
@ -100,35 +99,49 @@ module Ci
|
|||
end
|
||||
|
||||
def persist_data!
|
||||
in_lock(*lock_params) do # Write operation is atomic
|
||||
unsafe_persist_to!(self.class.persistable_store)
|
||||
end
|
||||
in_lock(*lock_params) { unsafe_persist_data! }
|
||||
end
|
||||
|
||||
def schedule_to_persist!
|
||||
return if persisted?
|
||||
|
||||
Ci::BuildTraceChunkFlushWorker.perform_async(id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def unsafe_persist_to!(new_store)
|
||||
def get_data
|
||||
# Redis / database return UTF-8 encoded string by default
|
||||
current_store.data(self)&.force_encoding(Encoding::BINARY)
|
||||
end
|
||||
|
||||
def unsafe_persist_data!(new_store = self.class.persistable_store)
|
||||
return if data_store == new_store.to_s
|
||||
|
||||
current_data = get_data
|
||||
current_data = data
|
||||
old_store_class = current_store
|
||||
|
||||
unless current_data&.bytesize.to_i == CHUNK_SIZE
|
||||
raise FailedToPersistDataError, 'Data is not fulfilled in a bucket'
|
||||
end
|
||||
|
||||
old_store_class = current_store
|
||||
|
||||
self.raw_data = nil
|
||||
self.data_store = new_store
|
||||
self.checksum = crc32(current_data)
|
||||
|
||||
##
|
||||
# We need to so persist data then save a new store identifier before we
|
||||
# remove data from the previous store to make this operation
|
||||
# trasnaction-safe. `unsafe_set_data! calls `save!` because of this
|
||||
# reason.
|
||||
#
|
||||
# TODO consider using callbacks and state machine to remove old data
|
||||
#
|
||||
unsafe_set_data!(current_data)
|
||||
|
||||
old_store_class.delete_data(self)
|
||||
end
|
||||
|
||||
def get_data
|
||||
current_store.data(self)&.force_encoding(Encoding::BINARY) # Redis/Database return UTF-8 string as default
|
||||
end
|
||||
|
||||
def unsafe_set_data!(value)
|
||||
raise ArgumentError, 'New data size exceeds chunk size' if value.bytesize > CHUNK_SIZE
|
||||
|
||||
|
@ -157,14 +170,12 @@ module Ci
|
|||
save! if changed?
|
||||
end
|
||||
|
||||
def schedule_to_persist
|
||||
return if data_persisted?
|
||||
|
||||
Ci::BuildTraceChunkFlushWorker.perform_async(id)
|
||||
def persisted?
|
||||
!redis?
|
||||
end
|
||||
|
||||
def data_persisted?
|
||||
!redis?
|
||||
def live?
|
||||
redis?
|
||||
end
|
||||
|
||||
def full?
|
||||
|
|
|
@ -29,7 +29,7 @@ module Ci
|
|||
new_data = truncated_data + new_data
|
||||
end
|
||||
|
||||
model.raw_data = new_data
|
||||
set_data(model, new_data)
|
||||
model.raw_data.to_s.bytesize
|
||||
end
|
||||
|
||||
|
|
|
@ -41,9 +41,9 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def set_data(model, data)
|
||||
def set_data(model, new_data)
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.set(key(model), data, ex: CHUNK_REDIS_TTL)
|
||||
redis.set(key(model), new_data, ex: CHUNK_REDIS_TTL)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
module Checksummable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def crc32(data)
|
||||
Zlib.crc32(data)
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def hexdigest(path)
|
||||
Digest::SHA256.file(path).hexdigest
|
||||
::Digest::SHA256.file(path).hexdigest
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,9 +6,9 @@ module Ci
|
|||
include PipelineBackgroundQueue
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def perform(build_trace_chunk_id)
|
||||
::Ci::BuildTraceChunk.find_by(id: build_trace_chunk_id).try do |build_trace_chunk|
|
||||
build_trace_chunk.persist_data!
|
||||
def perform(chunk_id)
|
||||
::Ci::BuildTraceChunk.find_by(id: chunk_id).try do |chunk|
|
||||
chunk.persist_data!
|
||||
end
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update issue edit buttons
|
||||
merge_request: 40298
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Make cloud native build logs more resilient
|
||||
merge_request: 40506
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddChecksumToBuildChunk < ActiveRecord::Migration[6.0]
|
||||
DOWNTIME = false
|
||||
|
||||
def change
|
||||
add_column :ci_build_trace_chunks, :checksum, :binary
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
39d412a1680d55466c14450943e17802eb183f2f33f2f77078cba571262cd149
|
|
@ -9782,7 +9782,8 @@ CREATE TABLE public.ci_build_trace_chunks (
|
|||
build_id integer NOT NULL,
|
||||
chunk_index integer NOT NULL,
|
||||
data_store integer NOT NULL,
|
||||
raw_data bytea
|
||||
raw_data bytea,
|
||||
checksum bytea
|
||||
);
|
||||
|
||||
CREATE SEQUENCE public.ci_build_trace_chunks_id_seq
|
||||
|
|
|
@ -14,6 +14,7 @@ first: '\b([A-Z]{3,5})\b'
|
|||
second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
|
||||
# ... with the exception of these:
|
||||
exceptions:
|
||||
- ANSI
|
||||
- API
|
||||
- ARN
|
||||
- ASCII
|
||||
|
@ -24,11 +25,15 @@ exceptions:
|
|||
- CPU
|
||||
- CSS
|
||||
- CSV
|
||||
- DAST
|
||||
- DNS
|
||||
- EKS
|
||||
- FAQ
|
||||
- FOSS
|
||||
- GCP
|
||||
- GDK
|
||||
- GET
|
||||
- GKE
|
||||
- GNU
|
||||
- GPG
|
||||
- GPL
|
||||
|
@ -47,6 +52,8 @@ exceptions:
|
|||
- LESS
|
||||
- LFS
|
||||
- LRU
|
||||
- MIME
|
||||
- MVC
|
||||
- NFS
|
||||
- NGINX
|
||||
- NOTE
|
||||
|
@ -61,11 +68,15 @@ exceptions:
|
|||
- RPC
|
||||
- RSA
|
||||
- RSS
|
||||
- RVM
|
||||
- SAML
|
||||
- SAST
|
||||
- SCIM
|
||||
- SCP
|
||||
- SCSS
|
||||
- SDK
|
||||
- SHA
|
||||
- SMTP
|
||||
- SQL
|
||||
- SSH
|
||||
- SSL
|
||||
|
@ -84,5 +95,6 @@ exceptions:
|
|||
- UUID
|
||||
- VPC
|
||||
- WIP
|
||||
- WSL
|
||||
- XML
|
||||
- YAML
|
||||
|
|
|
@ -744,7 +744,11 @@ so `&&` is evaluated before `||`.
|
|||
|
||||
#### Parentheses
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3
|
||||
> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default.
|
||||
> - It's enabled on GitLab.com.
|
||||
> - It's recommended for production use.
|
||||
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables-core-only). **(CORE ONLY)**
|
||||
|
||||
It is possible to use parentheses to group conditions. Parentheses have the highest
|
||||
precedence of all operators. Expressions enclosed in parentheses are evaluated first,
|
||||
|
@ -760,22 +764,24 @@ Examples:
|
|||
- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3`
|
||||
- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)`
|
||||
|
||||
##### Enable or disable parenthesis support for variables **(CORE ONLY)**
|
||||
|
||||
The feature is currently deployed behind a feature flag that is **enabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
|
||||
can opt to disable it for your instance.
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:ci_if_parenthesis_enabled)
|
||||
```
|
||||
|
||||
To disable it:
|
||||
|
||||
```ruby
|
||||
Feature.disable(:ci_if_parenthesis_enabled)
|
||||
```
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:ci_if_parenthesis_enabled)
|
||||
```
|
||||
|
||||
### Storing regular expressions in variables
|
||||
|
||||
It is possible to store a regular expression in a variable, to be used for pattern matching:
|
||||
|
|
|
@ -1548,6 +1548,22 @@ considered for their usage and behavior in this context. Future keyword improvem
|
|||
are being discussed in our [epic for improving `rules`](https://gitlab.com/groups/gitlab-org/-/epics/2783),
|
||||
where anyone can add suggestions or requests.
|
||||
|
||||
You can use [parentheses](../variables/README.md#parentheses) with `&&` and `||` to build more complicated variable expressions.
|
||||
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3:
|
||||
|
||||
```yaml
|
||||
job1:
|
||||
script:
|
||||
- echo This rule uses parentheses.
|
||||
rules:
|
||||
if: ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
|
||||
```
|
||||
|
||||
NOTE: **Note:**
|
||||
In GitLab 13.2 and older, the order of operations when mixing `||` and `&&` in a single rule may not have executed
|
||||
in the expected order. This is [fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/230938)
|
||||
in GitLab 13.3.
|
||||
|
||||
### `only`/`except` (basic)
|
||||
|
||||
NOTE: **Note:**
|
||||
|
@ -1833,7 +1849,17 @@ end-to-end:
|
|||
- $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/
|
||||
```
|
||||
|
||||
Learn more about [variables expressions](../variables/README.md#environment-variables-expressions).
|
||||
You can use [parentheses](../variables/README.md#parentheses) with `&&` and `||` to build more complicated variable expressions.
|
||||
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3:
|
||||
|
||||
```yaml
|
||||
job1:
|
||||
script:
|
||||
- echo This rule uses parentheses.
|
||||
only:
|
||||
variables:
|
||||
- ($CI_COMMIT_BRANCH == "master" || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
|
||||
```
|
||||
|
||||
#### `only:changes`/`except:changes`
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ module Gitlab
|
|||
|
||||
# We assume 'value' must be mutable, given
|
||||
# that frozen string is enabled.
|
||||
|
||||
##
|
||||
# TODO We need to remove this because it is going to change checksum of
|
||||
# a trace.
|
||||
#
|
||||
value.gsub!(token, 'x' * token.length)
|
||||
value
|
||||
end
|
||||
|
|
|
@ -59,7 +59,7 @@ sast:
|
|||
bandit-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "SAST_ANALYZER_IMAGE"
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
|
@ -73,7 +73,7 @@ bandit-sast:
|
|||
brakeman-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "SAST_ANALYZER_IMAGE"
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
|
@ -105,7 +105,7 @@ eslint-sast:
|
|||
flawfinder-sast:
|
||||
extends: .sast-analyzer
|
||||
image:
|
||||
name: "SAST_ANALYZER_IMAGE"
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
|
||||
rules:
|
||||
|
|
|
@ -70,16 +70,6 @@ describe('Edit Actions components', () => {
|
|||
expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
|
||||
});
|
||||
|
||||
it('shows loading icon after clicking save button', done => {
|
||||
vm.$el.querySelector('.btn-success').click();
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.querySelector('.btn-success .fa')).not.toBeNull();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('disabled button after clicking save button', done => {
|
||||
vm.$el.querySelector('.btn-success').click();
|
||||
|
||||
|
@ -107,17 +97,6 @@ describe('Edit Actions components', () => {
|
|||
expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
|
||||
});
|
||||
|
||||
it('shows loading icon after clicking delete button', done => {
|
||||
jest.spyOn(window, 'confirm').mockReturnValue(true);
|
||||
vm.$el.querySelector('.btn-danger').click();
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.querySelector('.btn-danger .fa')).not.toBeNull();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does no actions when confirm is false', done => {
|
||||
jest.spyOn(window, 'confirm').mockReturnValue(false);
|
||||
vm.$el.querySelector('.btn-danger').click();
|
||||
|
|
|
@ -222,6 +222,8 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
|
|||
subject
|
||||
|
||||
build_trace_chunk.reload
|
||||
|
||||
expect(build_trace_chunk.checksum).to be_present
|
||||
expect(build_trace_chunk.fog?).to be_truthy
|
||||
expect(build_trace_chunk.data).to eq(new_data)
|
||||
end
|
||||
|
@ -502,6 +504,12 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
|
|||
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
|
||||
end
|
||||
|
||||
it 'calculates CRC32 checksum' do
|
||||
subject
|
||||
|
||||
expect(build_trace_chunk.reload.checksum).to eq '3398914352'
|
||||
end
|
||||
|
||||
it_behaves_like 'Atomic operation'
|
||||
end
|
||||
|
||||
|
|
|
@ -46,9 +46,7 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
|
|||
end
|
||||
|
||||
describe '#set_data' do
|
||||
subject { data_store.set_data(model, data) }
|
||||
|
||||
let(:data) { 'abc123' }
|
||||
let(:new_data) { 'abc123' }
|
||||
|
||||
context 'when data exists' do
|
||||
let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
|
||||
|
@ -56,9 +54,9 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
|
|||
it 'overwrites data' do
|
||||
expect(data_store.data(model)).to eq('sample data in fog')
|
||||
|
||||
subject
|
||||
data_store.set_data(model, new_data)
|
||||
|
||||
expect(data_store.data(model)).to eq('abc123')
|
||||
expect(data_store.data(model)).to eq new_data
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -68,9 +66,9 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
|
|||
it 'sets new data' do
|
||||
expect(data_store.data(model)).to be_nil
|
||||
|
||||
subject
|
||||
data_store.set_data(model, new_data)
|
||||
|
||||
expect(data_store.data(model)).to eq('abc123')
|
||||
expect(data_store.data(model)).to eq new_data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue