Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c01895daab
commit
cf73ed7d11
|
@ -1,9 +1,7 @@
|
||||||
/* eslint-disable class-methods-use-this */
|
/* eslint-disable class-methods-use-this */
|
||||||
/* eslint-disable @gitlab/require-i18n-strings */
|
|
||||||
|
|
||||||
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
|
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
|
||||||
import { Node } from 'tiptap';
|
import { Node } from 'tiptap';
|
||||||
import { HIGHER_PARSE_RULE_PRIORITY } from '../constants';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for playable media, like video and audio.
|
* Abstract base class for playable media, like video and audio.
|
||||||
|
@ -32,34 +30,34 @@ export default class Playable extends Node {
|
||||||
|
|
||||||
const parseDOM = [
|
const parseDOM = [
|
||||||
{
|
{
|
||||||
tag: `.${this.mediaType}-container`,
|
tag: `.media-container`,
|
||||||
skip: true,
|
getAttrs: (el) => ({
|
||||||
},
|
src: el.querySelector('audio,video').src,
|
||||||
{
|
alt: el.querySelector('audio,video').dataset.title,
|
||||||
tag: `.${this.mediaType}-container p`,
|
}),
|
||||||
priority: HIGHER_PARSE_RULE_PRIORITY,
|
|
||||||
ignore: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag: `${this.mediaType}[src]`,
|
|
||||||
getAttrs: (el) => ({ src: el.src, alt: el.dataset.title }),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const toDOM = (node) => [
|
const toDOM = (node) => [
|
||||||
this.mediaType,
|
'span',
|
||||||
{
|
{ class: 'media-container' },
|
||||||
src: node.attrs.src,
|
[
|
||||||
controls: true,
|
this.options.mediaType,
|
||||||
'data-setup': '{}',
|
{
|
||||||
'data-title': node.attrs.alt,
|
src: node.attrs.src,
|
||||||
...this.extraElementAttrs,
|
controls: true,
|
||||||
},
|
'data-setup': '{}',
|
||||||
|
'data-title': node.attrs.alt,
|
||||||
|
...this.extraElementAttrs,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
['a', { href: node.attrs.src }, node.attrs.alt],
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
attrs,
|
attrs,
|
||||||
group: 'block',
|
group: 'inline',
|
||||||
|
inline: true,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
parseDOM,
|
parseDOM,
|
||||||
toDOM,
|
toDOM,
|
||||||
|
@ -68,6 +66,5 @@ export default class Playable extends Node {
|
||||||
|
|
||||||
toMarkdown(state, node) {
|
toMarkdown(state, node) {
|
||||||
defaultMarkdownSerializer.nodes.image(state, node);
|
defaultMarkdownSerializer.nodes.image(state, node);
|
||||||
state.closeBlock(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Playable from './playable';
|
||||||
|
|
||||||
|
export default Playable.extend({
|
||||||
|
defaultOptions: {
|
||||||
|
...Playable.options,
|
||||||
|
mediaType: 'audio',
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Node } from '@tiptap/core';
|
||||||
|
|
||||||
|
const queryPlayableElement = (element, mediaType) => element.querySelector(mediaType);
|
||||||
|
|
||||||
|
export default Node.create({
|
||||||
|
name: 'playable',
|
||||||
|
group: 'inline',
|
||||||
|
inline: true,
|
||||||
|
draggable: true,
|
||||||
|
|
||||||
|
addAttributes() {
|
||||||
|
return {
|
||||||
|
src: {
|
||||||
|
default: null,
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const playable = queryPlayableElement(element, this.options.mediaType);
|
||||||
|
|
||||||
|
return {
|
||||||
|
src: playable.src,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
canonicalSrc: {
|
||||||
|
default: null,
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const playable = queryPlayableElement(element, this.options.mediaType);
|
||||||
|
|
||||||
|
return {
|
||||||
|
canonicalSrc: playable.dataset.canonicalSrc,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
alt: {
|
||||||
|
default: null,
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const playable = queryPlayableElement(element, this.options.mediaType);
|
||||||
|
|
||||||
|
return {
|
||||||
|
alt: playable.dataset.title,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: '.media-container',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ node }) {
|
||||||
|
return [
|
||||||
|
'span',
|
||||||
|
{ class: 'media-container' },
|
||||||
|
[
|
||||||
|
this.options.mediaType,
|
||||||
|
{
|
||||||
|
src: node.attrs.src,
|
||||||
|
controls: true,
|
||||||
|
'data-setup': '{}',
|
||||||
|
'data-title': node.attrs.alt,
|
||||||
|
...this.extraElementAttrs,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
['a', { href: node.attrs.src }, node.attrs.alt],
|
||||||
|
];
|
||||||
|
},
|
||||||
|
});
|
|
@ -2,6 +2,7 @@ import { Editor } from '@tiptap/vue-2';
|
||||||
import { isFunction } from 'lodash';
|
import { isFunction } from 'lodash';
|
||||||
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
|
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
|
||||||
import Attachment from '../extensions/attachment';
|
import Attachment from '../extensions/attachment';
|
||||||
|
import Audio from '../extensions/audio';
|
||||||
import Blockquote from '../extensions/blockquote';
|
import Blockquote from '../extensions/blockquote';
|
||||||
import Bold from '../extensions/bold';
|
import Bold from '../extensions/bold';
|
||||||
import BulletList from '../extensions/bullet_list';
|
import BulletList from '../extensions/bullet_list';
|
||||||
|
@ -63,6 +64,7 @@ export const createContentEditor = ({
|
||||||
|
|
||||||
const builtInContentEditorExtensions = [
|
const builtInContentEditorExtensions = [
|
||||||
Attachment.configure({ uploadsPath, renderMarkdown }),
|
Attachment.configure({ uploadsPath, renderMarkdown }),
|
||||||
|
Audio,
|
||||||
Blockquote,
|
Blockquote,
|
||||||
Bold,
|
Bold,
|
||||||
BulletList,
|
BulletList,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
defaultMarkdownSerializer,
|
defaultMarkdownSerializer,
|
||||||
} from 'prosemirror-markdown/src/to_markdown';
|
} from 'prosemirror-markdown/src/to_markdown';
|
||||||
import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
||||||
|
import Audio from '../extensions/audio';
|
||||||
import Blockquote from '../extensions/blockquote';
|
import Blockquote from '../extensions/blockquote';
|
||||||
import Bold from '../extensions/bold';
|
import Bold from '../extensions/bold';
|
||||||
import BulletList from '../extensions/bullet_list';
|
import BulletList from '../extensions/bullet_list';
|
||||||
|
@ -40,6 +41,8 @@ import {
|
||||||
openTag,
|
openTag,
|
||||||
closeTag,
|
closeTag,
|
||||||
renderOrderedList,
|
renderOrderedList,
|
||||||
|
renderImage,
|
||||||
|
renderPlayable,
|
||||||
} from './serialization_helpers';
|
} from './serialization_helpers';
|
||||||
|
|
||||||
const defaultSerializerConfig = {
|
const defaultSerializerConfig = {
|
||||||
|
@ -92,6 +95,7 @@ const defaultSerializerConfig = {
|
||||||
},
|
},
|
||||||
|
|
||||||
nodes: {
|
nodes: {
|
||||||
|
[Audio.name]: renderPlayable,
|
||||||
[Blockquote.name]: (state, node) => {
|
[Blockquote.name]: (state, node) => {
|
||||||
if (node.attrs.multiline) {
|
if (node.attrs.multiline) {
|
||||||
state.write('>>>');
|
state.write('>>>');
|
||||||
|
@ -120,12 +124,7 @@ const defaultSerializerConfig = {
|
||||||
[HardBreak.name]: renderHardBreak,
|
[HardBreak.name]: renderHardBreak,
|
||||||
[Heading.name]: defaultMarkdownSerializer.nodes.heading,
|
[Heading.name]: defaultMarkdownSerializer.nodes.heading,
|
||||||
[HorizontalRule.name]: defaultMarkdownSerializer.nodes.horizontal_rule,
|
[HorizontalRule.name]: defaultMarkdownSerializer.nodes.horizontal_rule,
|
||||||
[Image.name]: (state, node) => {
|
[Image.name]: renderImage,
|
||||||
const { alt, canonicalSrc, src, title } = node.attrs;
|
|
||||||
const quotedTitle = title ? ` ${state.quote(title)}` : '';
|
|
||||||
|
|
||||||
state.write(`![${state.esc(alt || '')}](${state.esc(canonicalSrc || src)}${quotedTitle})`);
|
|
||||||
},
|
|
||||||
[ListItem.name]: defaultMarkdownSerializer.nodes.list_item,
|
[ListItem.name]: defaultMarkdownSerializer.nodes.list_item,
|
||||||
[OrderedList.name]: renderOrderedList,
|
[OrderedList.name]: renderOrderedList,
|
||||||
[Paragraph.name]: defaultMarkdownSerializer.nodes.paragraph,
|
[Paragraph.name]: defaultMarkdownSerializer.nodes.paragraph,
|
||||||
|
|
|
@ -286,3 +286,14 @@ export function renderHardBreak(state, node, parent, index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderImage(state, node) {
|
||||||
|
const { alt, canonicalSrc, src, title } = node.attrs;
|
||||||
|
const quotedTitle = title ? ` ${state.quote(title)}` : '';
|
||||||
|
|
||||||
|
state.write(`![${state.esc(alt || '')}](${state.esc(canonicalSrc || src)}${quotedTitle})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderPlayable(state, node) {
|
||||||
|
renderImage(state, node);
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media-container {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: $gl-spacing-scale-2;
|
||||||
|
}
|
||||||
|
|
||||||
img:not(.emoji) {
|
img:not(.emoji) {
|
||||||
margin: 0 0 8px;
|
margin: 0 0 8px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ class CommitStatus < Ci::ApplicationRecord
|
||||||
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
|
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
|
||||||
scope :eager_load_pipeline, -> { eager_load(:pipeline, project: { namespace: :route }) }
|
scope :eager_load_pipeline, -> { eager_load(:pipeline, project: { namespace: :route }) }
|
||||||
scope :with_pipeline, -> { joins(:pipeline) }
|
scope :with_pipeline, -> { joins(:pipeline) }
|
||||||
scope :updated_at_before, ->(date) { where('ci_builds.updated_at < ?', date) }
|
|
||||||
scope :created_at_before, ->(date) { where('ci_builds.created_at < ?', date) }
|
scope :created_at_before, ->(date) { where('ci_builds.created_at < ?', date) }
|
||||||
|
scope :updated_at_before, ->(date) { where('ci_builds.updated_at < ?', date) }
|
||||||
scope :updated_before, ->(lookback:, timeout:) {
|
scope :updated_before, ->(lookback:, timeout:) {
|
||||||
where('(ci_builds.created_at BETWEEN ? AND ?) AND (ci_builds.updated_at BETWEEN ? AND ?)', lookback, timeout, lookback, timeout)
|
where('(ci_builds.created_at BETWEEN ? AND ?) AND (ci_builds.updated_at BETWEEN ? AND ?)', lookback, timeout, lookback, timeout)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,12 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
end
|
end
|
||||||
|
|
||||||
def running_timed_out_builds
|
def running_timed_out_builds
|
||||||
Ci::Build.running.where( # rubocop: disable CodeReuse/ActiveRecord
|
if Feature.enabled?(:ci_new_query_for_running_stuck_jobs)
|
||||||
'ci_builds.updated_at < ?',
|
running_builds = Ci::Build.running.created_at_before(BUILD_RUNNING_OUTDATED_TIMEOUT.ago).order(created_at: :asc, project_id: :asc) # rubocop: disable CodeReuse/ActiveRecord
|
||||||
BUILD_RUNNING_OUTDATED_TIMEOUT.ago
|
Ci::Build.id_in(running_builds).updated_at_before(BUILD_RUNNING_OUTDATED_TIMEOUT.ago)
|
||||||
)
|
else
|
||||||
|
Ci::Build.running.updated_at_before(BUILD_RUNNING_OUTDATED_TIMEOUT.ago)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def try_obtain_lease
|
def try_obtain_lease
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: ci_new_query_for_running_stuck_jobs
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68891
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339264
|
||||||
|
milestone: '14.3'
|
||||||
|
type: development
|
||||||
|
group: group::pipeline execution
|
||||||
|
default_enabled: false
|
|
@ -52,7 +52,7 @@ module Banzai
|
||||||
doc.document.create_element(media_type, media_element_attrs)
|
doc.document.create_element(media_type, media_element_attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_paragraph(doc, element)
|
def download_link(doc, element)
|
||||||
link_content = element['title'] || element['alt']
|
link_content = element['title'] || element['alt']
|
||||||
|
|
||||||
link_element_attrs = {
|
link_element_attrs = {
|
||||||
|
@ -67,19 +67,15 @@ module Banzai
|
||||||
link_element_attrs['data-canonical-src'] = element['data-canonical-src']
|
link_element_attrs['data-canonical-src'] = element['data-canonical-src']
|
||||||
end
|
end
|
||||||
|
|
||||||
link = doc.document.create_element('a', link_content, link_element_attrs)
|
doc.document.create_element('a', link_content, link_element_attrs)
|
||||||
|
|
||||||
doc.document.create_element('p').tap do |paragraph|
|
|
||||||
paragraph.children = link
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def media_node(doc, element)
|
def media_node(doc, element)
|
||||||
container_element_attrs = { class: "#{media_type}-container" }
|
container_element_attrs = { class: "media-container #{media_type}-container" }
|
||||||
|
|
||||||
doc.document.create_element( "div", container_element_attrs).tap do |container|
|
doc.document.create_element('span', container_element_attrs).tap do |container|
|
||||||
container.add_child(media_element(doc, element))
|
container.add_child(media_element(doc, element))
|
||||||
container.add_child(download_paragraph(doc, element))
|
container.add_child(download_link(doc, element))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -145,3 +145,15 @@
|
||||||
context: project_wiki
|
context: project_wiki
|
||||||
markdown: |-
|
markdown: |-
|
||||||
Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1
|
Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1
|
||||||
|
- name: audio
|
||||||
|
markdown: '![Sample Audio](https://gitlab.com/gitlab.mp3)'
|
||||||
|
- name: audio_in_lists
|
||||||
|
markdown: |-
|
||||||
|
* ![Sample Audio](https://gitlab.com/1.mp3)
|
||||||
|
* ![Sample Audio](https://gitlab.com/2.mp3)
|
||||||
|
|
||||||
|
1. ![Sample Audio](https://gitlab.com/1.mp3)
|
||||||
|
2. ![Sample Audio](https://gitlab.com/2.mp3)
|
||||||
|
|
||||||
|
* [x] ![Sample Audio](https://gitlab.com/1.mp3)
|
||||||
|
* [x] ![Sample Audio](https://gitlab.com/2.mp3)
|
||||||
|
|
|
@ -25,18 +25,14 @@ RSpec.describe Banzai::Filter::AudioLinkFilter do
|
||||||
it 'replaces the image tag with an audio tag' do
|
it 'replaces the image tag with an audio tag' do
|
||||||
container = filter(image).children.first
|
container = filter(image).children.first
|
||||||
|
|
||||||
expect(container.name).to eq 'div'
|
expect(container.name).to eq 'span'
|
||||||
expect(container['class']).to eq 'audio-container'
|
expect(container['class']).to eq 'media-container audio-container'
|
||||||
|
|
||||||
audio, paragraph = container.children
|
audio, link = container.children
|
||||||
|
|
||||||
expect(audio.name).to eq 'audio'
|
expect(audio.name).to eq 'audio'
|
||||||
expect(audio['src']).to eq src
|
expect(audio['src']).to eq src
|
||||||
|
|
||||||
expect(paragraph.name).to eq 'p'
|
|
||||||
|
|
||||||
link = paragraph.children.first
|
|
||||||
|
|
||||||
expect(link.name).to eq 'a'
|
expect(link.name).to eq 'a'
|
||||||
expect(link['href']).to eq src
|
expect(link['href']).to eq src
|
||||||
expect(link['target']).to eq '_blank'
|
expect(link['target']).to eq '_blank'
|
||||||
|
@ -105,15 +101,13 @@ RSpec.describe Banzai::Filter::AudioLinkFilter do
|
||||||
image = %(<img src="#{proxy_src}" data-canonical-src="#{canonical_src}"/>)
|
image = %(<img src="#{proxy_src}" data-canonical-src="#{canonical_src}"/>)
|
||||||
container = filter(image).children.first
|
container = filter(image).children.first
|
||||||
|
|
||||||
expect(container['class']).to eq 'audio-container'
|
expect(container['class']).to eq 'media-container audio-container'
|
||||||
|
|
||||||
audio, paragraph = container.children
|
audio, link = container.children
|
||||||
|
|
||||||
expect(audio['src']).to eq proxy_src
|
expect(audio['src']).to eq proxy_src
|
||||||
expect(audio['data-canonical-src']).to eq canonical_src
|
expect(audio['data-canonical-src']).to eq canonical_src
|
||||||
|
|
||||||
link = paragraph.children.first
|
|
||||||
|
|
||||||
expect(link['href']).to eq proxy_src
|
expect(link['href']).to eq proxy_src
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,20 +25,16 @@ RSpec.describe Banzai::Filter::VideoLinkFilter do
|
||||||
it 'replaces the image tag with a video tag' do
|
it 'replaces the image tag with a video tag' do
|
||||||
container = filter(image).children.first
|
container = filter(image).children.first
|
||||||
|
|
||||||
expect(container.name).to eq 'div'
|
expect(container.name).to eq 'span'
|
||||||
expect(container['class']).to eq 'video-container'
|
expect(container['class']).to eq 'media-container video-container'
|
||||||
|
|
||||||
video, paragraph = container.children
|
video, link = container.children
|
||||||
|
|
||||||
expect(video.name).to eq 'video'
|
expect(video.name).to eq 'video'
|
||||||
expect(video['src']).to eq src
|
expect(video['src']).to eq src
|
||||||
expect(video['width']).to eq "400"
|
expect(video['width']).to eq "400"
|
||||||
expect(video['preload']).to eq 'metadata'
|
expect(video['preload']).to eq 'metadata'
|
||||||
|
|
||||||
expect(paragraph.name).to eq 'p'
|
|
||||||
|
|
||||||
link = paragraph.children.first
|
|
||||||
|
|
||||||
expect(link.name).to eq 'a'
|
expect(link.name).to eq 'a'
|
||||||
expect(link['href']).to eq src
|
expect(link['href']).to eq src
|
||||||
expect(link['target']).to eq '_blank'
|
expect(link['target']).to eq '_blank'
|
||||||
|
@ -107,15 +103,13 @@ RSpec.describe Banzai::Filter::VideoLinkFilter do
|
||||||
image = %(<img src="#{proxy_src}" data-canonical-src="#{canonical_src}"/>)
|
image = %(<img src="#{proxy_src}" data-canonical-src="#{canonical_src}"/>)
|
||||||
container = filter(image).children.first
|
container = filter(image).children.first
|
||||||
|
|
||||||
expect(container['class']).to eq 'video-container'
|
expect(container['class']).to eq 'media-container video-container'
|
||||||
|
|
||||||
video, paragraph = container.children
|
video, link = container.children
|
||||||
|
|
||||||
expect(video['src']).to eq proxy_src
|
expect(video['src']).to eq proxy_src
|
||||||
expect(video['data-canonical-src']).to eq canonical_src
|
expect(video['data-canonical-src']).to eq canonical_src
|
||||||
|
|
||||||
link = paragraph.children.first
|
|
||||||
|
|
||||||
expect(link['href']).to eq proxy_src
|
expect(link['href']).to eq proxy_src
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -186,20 +186,32 @@ RSpec.describe StuckCiJobsWorker do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when job is running' do
|
shared_examples 'job is running' do
|
||||||
let(:status) { 'running' }
|
context 'when job is running' do
|
||||||
|
let(:status) { 'running' }
|
||||||
|
|
||||||
context 'when job was updated_at more than an hour ago' do
|
context 'when job was updated_at more than an hour ago' do
|
||||||
let(:updated_at) { 2.hours.ago }
|
let(:updated_at) { 2.hours.ago }
|
||||||
|
|
||||||
it_behaves_like 'job is dropped'
|
it_behaves_like 'job is dropped'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when job was updated in less than 1 hour ago' do
|
||||||
|
let(:updated_at) { 30.minutes.ago }
|
||||||
|
|
||||||
|
it_behaves_like 'job is unchanged'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'job is running'
|
||||||
|
|
||||||
|
context 'when ci_new_query_for_running_stuck_jobs feature flag is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(ci_new_query_for_running_stuck_jobs: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when job was updated in less than 1 hour ago' do
|
it_behaves_like 'job is running'
|
||||||
let(:updated_at) { 30.minutes.ago }
|
|
||||||
|
|
||||||
it_behaves_like 'job is unchanged'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(success skipped failed canceled).each do |status|
|
%w(success skipped failed canceled).each do |status|
|
||||||
|
|
Loading…
Reference in New Issue