提交 ba2345d7 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 29471900
<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
......
---
title: Update issue edit buttons
merge_request: 40298
author:
type: changed
---
title: Make cloud native build logs more resilient
merge_request: 40506
author:
type: added
# frozen_string_literal: true
class AddChecksumToBuildChunk < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :ci_build_trace_chunks, :checksum, :binary
end
end
39d412a1680d55466c14450943e17802eb183f2f33f2f77078cba571262cd149
\ No newline at end of file
......@@ -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,20 +764,22 @@ 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:
To disable it:
```ruby
Feature.enable(:ci_if_parenthesis_enabled)
Feature.disable(:ci_if_parenthesis_enabled)
```
To disable it:
To enable it:
```ruby
Feature.disable(:ci_if_parenthesis_enabled)
Feature.enable(:ci_if_parenthesis_enabled)
```
### Storing regular expressions in variables
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册