Add latest changes from gitlab-org/gitlab@master
|
|
@ -1 +1 @@
|
|||
0f93ceb8a8ccfe38ee3fde399efcb49aa91cbedd
|
||||
61404ee4997721100430c6acf4586ec3d85b15da
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const getDraftComments = (state) => {
|
|||
}
|
||||
|
||||
return state.batchComments.drafts
|
||||
.filter((draft) => !draft.line_code && !draft.discussion_id)
|
||||
.filter((draft) => !draft.file_path && !draft.discussion_id)
|
||||
.map((x) => ({
|
||||
...x,
|
||||
// Treat a top-level draft note as individual_note so it's not included in
|
||||
|
|
|
|||
|
|
@ -74,4 +74,4 @@ export const PIPELINES_DETAIL_LINKS_MEASURE_CALCULATION =
|
|||
// (defined in: app/services/ci/prometheus_metrics/observe_histograms_service.rb)
|
||||
export const PIPELINES_DETAIL_LINK_DURATION = 'pipeline_graph_link_calculation_duration_seconds';
|
||||
export const PIPELINES_DETAIL_LINKS_TOTAL = 'pipeline_graph_links_total';
|
||||
export const PIPELINES_DETAIL_LINKS_JOB_RATIO = 'pipeline_graph_link_per_job_ratio';
|
||||
export const PIPELINES_DETAIL_LINKS_JOB_RATIO = 'pipeline_graph_links_per_job_ratio';
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ module Issuable
|
|||
end
|
||||
|
||||
def group_for(issuable)
|
||||
issuable.resource_parent
|
||||
issuable.resource_parent.group
|
||||
end
|
||||
|
||||
def delete_todos(issuable)
|
||||
group = group_for(issuable)
|
||||
actor = group_for(issuable)
|
||||
|
||||
if Feature.enabled?(:destroy_issuable_todos_async, group, default_enabled: :yaml)
|
||||
if Feature.enabled?(:destroy_issuable_todos_async, actor, default_enabled: :yaml)
|
||||
TodosDestroyer::DestroyedIssuableWorker
|
||||
.perform_async(issuable.id, issuable.class.name)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
|
|||
## Atlassian application registration
|
||||
|
||||
1. Go to <https://developer.atlassian.com/apps/> and sign-in with the Atlassian
|
||||
account to administer the application with.
|
||||
account that will administer the application.
|
||||
|
||||
1. Click **Create a new app**.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
To enable the Authentiq OmniAuth provider for passwordless authentication you must register an application with Authentiq.
|
||||
|
||||
Authentiq generates a Client ID and the accompanying Client Secret for you to use.
|
||||
Authentiq will generate a Client ID and the accompanying Client Secret for you to use.
|
||||
|
||||
1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/developers).
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -15,14 +15,14 @@ Jobs can output an archive of files and directories. This output is known as a j
|
|||
You can download job artifacts by using the GitLab UI or the [API](../../api/job_artifacts.md#get-job-artifacts).
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
For an overview, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s).
|
||||
Watch also [GitLab CI pipeline tutorial for beginners](https://www.youtube.com/watch?v=Jav4vbUrqII).
|
||||
For an overview of job artifacts, watch the video [GitLab CI pipelines, artifacts, and environments](https://www.youtube.com/watch?v=PCKDICEe10s).
|
||||
Or, for an introduction, watch [GitLab CI pipeline tutorial for beginners](https://www.youtube.com/watch?v=Jav4vbUrqII).
|
||||
|
||||
Administrators should review our [job artifacts administration](../../administration/job_artifacts.md) documentation.
|
||||
For administrator information about job artifact storage, see [administering job artifacts](../../administration/job_artifacts.md).
|
||||
|
||||
## Define artifacts in the `.gitlab-ci.yml` file
|
||||
## Create job artifacts
|
||||
|
||||
This example shows how to configure your `.gitlab-ci.yml` file to create job artifacts:
|
||||
To create job artifacts, use the `artifacts` keyword in your `.gitlab-ci.yml` file:
|
||||
|
||||
```yaml
|
||||
pdf:
|
||||
|
|
@ -33,7 +33,7 @@ pdf:
|
|||
expire_in: 1 week
|
||||
```
|
||||
|
||||
A job named `pdf` calls the `xelatex` command to build a PDF file from the
|
||||
In this example, a job named `pdf` calls the `xelatex` command to build a PDF file from the
|
||||
LaTeX source file, `mycv.tex`.
|
||||
|
||||
The `paths` keyword determines which files to add to the job artifacts.
|
||||
|
|
@ -45,6 +45,9 @@ If `expire_in` is not defined, the
|
|||
[instance-wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
|
||||
is used.
|
||||
|
||||
If you run two types of pipelines (like branch and scheduled) for the same ref,
|
||||
the pipeline that finishes later creates the job artifact.
|
||||
|
||||
For more examples, view the [keyword reference for the `.gitlab-ci.yml` file](../yaml/README.md#artifacts).
|
||||
|
||||
## Download job artifacts
|
||||
|
|
@ -53,23 +56,23 @@ You can download job artifacts or view the job archive:
|
|||
|
||||
- On the **Pipelines** page, to the right of the pipeline:
|
||||
|
||||

|
||||

|
||||
|
||||
- On the **Jobs** page, to the right of the job:
|
||||
|
||||

|
||||

|
||||
|
||||
- On a job's detail page. The **Keep** button indicates an `expire_in` value was set:
|
||||
|
||||

|
||||

|
||||
|
||||
- On a merge request, by the pipeline details:
|
||||
|
||||

|
||||

|
||||
|
||||
- When browsing an archive:
|
||||
|
||||

|
||||

|
||||
|
||||
If [GitLab Pages](../../administration/pages/index.md) is enabled in the project, you can preview
|
||||
HTML files in the artifacts directly in your browser. If the project is internal or private, you must
|
||||
|
|
@ -83,44 +86,37 @@ information in the UI.
|
|||
|
||||

|
||||
|
||||
## Erase job artifacts
|
||||
## Delete job artifacts
|
||||
|
||||
WARNING:
|
||||
This is a destructive action that leads to data loss. Use with caution.
|
||||
|
||||
You can erase a single job, which also removes the job's
|
||||
You can delete a single job, which also removes the job's
|
||||
artifacts and log. You must be:
|
||||
|
||||
- The owner of the job.
|
||||
- A [Maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project.
|
||||
- A [maintainer](../../user/permissions.md#gitlab-cicd-permissions) of the project.
|
||||
|
||||
To erase a job:
|
||||
To delete a job:
|
||||
|
||||
1. Go to a job's detail page.
|
||||
1. At the top right of the job's log, select the trash icon.
|
||||
1. Confirm the deletion.
|
||||
|
||||
## Retrieve job artifacts for private projects
|
||||
## Retrieve job artifacts for other projects
|
||||
|
||||
To retrieve a job artifact from a different project, you might need to use a
|
||||
private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts)
|
||||
the artifact.
|
||||
|
||||
## The latest job artifacts
|
||||
|
||||
Job artifacts created in the most recent successful pipeline for a specific ref
|
||||
are considered the latest artifacts. If you run two types of pipelines for the same ref,
|
||||
timing determines which artifacts are the latest.
|
||||
|
||||
For example, if a merge request creates a branch pipeline at the same time as
|
||||
a scheduled pipeline, the pipeline that finished most recently creates the latest job artifact.
|
||||
## How searching for job artifacts works
|
||||
|
||||
In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts
|
||||
for [parent and child pipelines](../parent_child_pipelines.md) are searched in hierarchical
|
||||
order from parent to child. For example, if both parent and child pipelines have a
|
||||
job with the same name, the job artifact from the parent pipeline is returned.
|
||||
|
||||
### Access the latest job artifacts by URL
|
||||
## Access the latest job artifacts by URL
|
||||
|
||||
You can download the latest job artifacts by using a URL.
|
||||
|
||||
|
|
@ -136,12 +132,12 @@ To download a single file from the artifacts:
|
|||
https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
|
||||
```
|
||||
|
||||
For example, to download the latest artifacts of the job named `coverage` of
|
||||
the `master` branch of the `gitlab` project that belongs to the `gitlab-org`
|
||||
For example, to download the latest artifacts of the job named `coverage` in
|
||||
the `main` branch of the `gitlab` project in the `gitlab-org`
|
||||
namespace:
|
||||
|
||||
```plaintext
|
||||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/download?job=coverage
|
||||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/main/download?job=coverage
|
||||
```
|
||||
|
||||
To download the file `coverage/index.html` from the same artifacts:
|
||||
|
|
@ -162,7 +158,7 @@ For example:
|
|||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/browse?job=coverage
|
||||
```
|
||||
|
||||
There is also a URL for specific files, including HTML files that
|
||||
To download specific files, including HTML files that
|
||||
are shown in [GitLab Pages](../../administration/pages/index.md):
|
||||
|
||||
```plaintext
|
||||
|
|
@ -175,16 +171,18 @@ For example, when a job `coverage` creates the artifact `htmlcov/index.html`:
|
|||
https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage
|
||||
```
|
||||
|
||||
## When job artifacts are deleted
|
||||
|
||||
By default, the latest job artifacts from the most recent successful jobs are never deleted.
|
||||
If a job is configured with [`expire_in`](../yaml/README.md#artifactsexpire_in),
|
||||
its artifacts only expire if a more recent artifact exists.
|
||||
|
||||
### Keep artifacts from most recent successful jobs
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4.
|
||||
> - [Made optional with a CI/CD setting](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8.
|
||||
|
||||
By default, the latest job artifacts from the most recent successful jobs are never deleted.
|
||||
If a job is configured with [`expire_in`](../yaml/README.md#artifactsexpire_in),
|
||||
its artifacts only expire if a more recent artifact exists.
|
||||
|
||||
Keeping the latest artifacts can use a large amount of storage space in projects
|
||||
with a lot of jobs or large artifacts. If the latest artifacts are not needed in
|
||||
a project, you can disable this behavior to save space:
|
||||
|
|
@ -202,21 +200,9 @@ A new pipeline must run before the latest artifacts can expire and be deleted.
|
|||
|
||||
### Error message `No files to upload`
|
||||
|
||||
This is often preceded by other errors or warnings that specify the filename and why it wasn't
|
||||
generated in the first place. Please check the entire job log for such messages.
|
||||
This message is often preceded by other errors or warnings that specify the filename and why it wasn't
|
||||
generated. Check the job log for these messages.
|
||||
|
||||
If you find no helpful messages, please retry the failed job after activating
|
||||
If you find no helpful messages, retry the failed job after activating
|
||||
[CI/CD debug logging](../variables/README.md#debug-logging).
|
||||
This provides useful information to investigate further.
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
||||
one might have when setting this up, or when something is changed, or on upgrading, it's
|
||||
important to describe those, too. Think of things that may go wrong and include them here.
|
||||
This is important to minimize requests for support, and to avoid doc comments with
|
||||
questions that you know someone might ask.
|
||||
|
||||
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
|
||||
If you have none to add when creating a doc, leave this section in place
|
||||
but commented out to help encourage others to add to it in the future. -->
|
||||
This logging should provide information to help you investigate further.
|
||||
|
|
|
|||
|
|
@ -3270,7 +3270,7 @@ deploy:
|
|||
|
||||
If the artifacts of the job that is set as a dependency are
|
||||
[expired](#artifactsexpire_in) or
|
||||
[erased](../pipelines/job_artifacts.md#erase-job-artifacts), then
|
||||
[deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then
|
||||
the dependent job fails.
|
||||
|
||||
You can ask your administrator to
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ Before you push your changes, Lefthook automatically runs the following checks:
|
|||
- SCSS lint: Run `yarn lint:stylelint` checks (with the [`.stylelintrc`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.stylelintrc) configuration) on the modified `*.scss{,.css}` files. Tags: `stylesheet`, `css`, `style`.
|
||||
- RuboCop: Run `bundle exec rubocop` checks (with the [`.rubocop.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.rubocop.yml) configuration) on the modified `*.rb` files. Tags: `backend`, `style`.
|
||||
- Vale: Run `vale` checks (with the [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) configuration) on the modified `*.md` files. Tags: `documentation`, `style`.
|
||||
- Documentation metadata: Run checks for the absence of [documentation metadata](../documentation/index.md#metadata).
|
||||
|
||||
In addition to the default configuration, you can define a [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,10 @@ cron worker runs. Default value is 5 minutes.
|
|||
- `pause_indexing!` - Pause indexing while the migration runs. This setting will record the indexing setting before
|
||||
the migration runs and set it back to that value when the migration is completed.
|
||||
|
||||
- `space_requirements!` - Verify that enough free space is available in the cluster when the migration runs. This setting
|
||||
will halt the migration if the storage required is not available when the migration runs. The migration must provide
|
||||
the space required in bytes by defining a `space_required_bytes` method.
|
||||
|
||||
```ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
|
|
@ -248,7 +252,9 @@ class BatchedMigrationName < Elastic::Migration
|
|||
# Declares a migration should be run in batches
|
||||
batched!
|
||||
throttle_delay 10.minutes
|
||||
|
||||
pause_indexing!
|
||||
space_requirements!
|
||||
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
|
|
|||
|
|
@ -38,8 +38,3 @@ pre-push:
|
|||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: 'doc/*.md'
|
||||
run: if command -v vale 2> /dev/null; then vale --config .vale.ini --minAlertLevel error {files}; else echo "Vale not found. Install Vale"; fi
|
||||
docs-metadata: # https://docs.gitlab.com/ee/development/documentation/#metadata
|
||||
tags: documentation style
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '*.md'
|
||||
run: scripts/lint-docs-metadata.sh "{files}"
|
||||
|
|
|
|||
|
|
@ -98,11 +98,12 @@ module Gitlab
|
|||
end
|
||||
|
||||
def get_all_lfs_pointers
|
||||
request = Gitaly::GetAllLFSPointersRequest.new(
|
||||
repository: @gitaly_repo
|
||||
request = Gitaly::ListLFSPointersRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
revisions: [encode_binary("--all")]
|
||||
)
|
||||
|
||||
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_all_lfs_pointers, request, timeout: GitalyClient.medium_timeout)
|
||||
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :list_lfs_pointers, request, timeout: GitalyClient.medium_timeout)
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
|
||||
|
|
@ -125,19 +126,20 @@ module Gitlab
|
|||
|
||||
[request, :list_all_lfs_pointers]
|
||||
else
|
||||
request = Gitaly::GetNewLFSPointersRequest.new(
|
||||
revisions = [revision]
|
||||
revisions += if not_in.nil? || not_in == :all
|
||||
["--not", "--all"]
|
||||
else
|
||||
not_in.prepend "--not"
|
||||
end
|
||||
|
||||
request = Gitaly::ListLFSPointersRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
revision: encode_binary(revision),
|
||||
limit: limit || 0
|
||||
limit: limit || 0,
|
||||
revisions: revisions.map { |rev| encode_binary(rev) }
|
||||
)
|
||||
|
||||
if not_in.nil? || not_in == :all
|
||||
request.not_in_all = true
|
||||
else
|
||||
request.not_in_refs += not_in
|
||||
end
|
||||
|
||||
[request, :get_new_lfs_pointers]
|
||||
[request, :list_lfs_pointers]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module Gitlab
|
|||
DiskAccessDenied = Class.new(StandardError)
|
||||
|
||||
def path
|
||||
::Gitlab::ErrorTracking.track_exception(DiskAccessDenied.new) if disk_access_denied?
|
||||
report_denied_disk_access
|
||||
|
||||
super
|
||||
end
|
||||
|
|
@ -22,6 +22,12 @@ module Gitlab
|
|||
|
||||
::Gitlab::Runtime.web_server? && !::Gitlab::Runtime.test_suite?
|
||||
end
|
||||
|
||||
def report_denied_disk_access
|
||||
raise DiskAccessDenied if disk_access_denied?
|
||||
rescue => e
|
||||
::Gitlab::ErrorTracking.track_exception(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ then
|
|||
fi
|
||||
|
||||
# Documentation pages need front matter for tracking purposes.
|
||||
# See also lint-docs-metadata.sh
|
||||
echo '=> Checking documentation for front matter...'
|
||||
echo
|
||||
no_frontmatter=$(find doc -name "*.md" -exec head -n1 {} \; | grep -v --count -- ---)
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Used in `lefthook.yml`
|
||||
(( counter=0 ))
|
||||
|
||||
for file in $1
|
||||
do
|
||||
if [ "$(head -n1 "$file")" != "---" ]
|
||||
then
|
||||
printf "%sDocumentation metadata missing in %s%s\n" "$(tput setaf 1)" "$file" "$(tput sgr0)"
|
||||
(( counter++ ))
|
||||
else
|
||||
printf "Documentation metadata found in %s.\n" "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$counter" -gt 0 ]
|
||||
then
|
||||
printf "\n%sDocumentation metadata is missing in changed documentation files.%s For more information, see https://docs.gitlab.com/ee/development/documentation/#metadata.\n" "$(tput setaf 1)" "$(tput sgr0)"
|
||||
false
|
||||
else
|
||||
printf "\n%sDocumentation metadata found in all changed documentation files.%s\n" "$(tput setaf 2)" "$(tput sgr0)"
|
||||
true
|
||||
fi
|
||||
|
|
@ -9,17 +9,30 @@ FactoryBot.define do
|
|||
transient do
|
||||
line_number { 14 }
|
||||
diff_refs { merge_request.try(:diff_refs) }
|
||||
path { "files/ruby/popen.rb" }
|
||||
end
|
||||
|
||||
position do
|
||||
Gitlab::Diff::Position.new(
|
||||
old_path: "files/ruby/popen.rb",
|
||||
new_path: "files/ruby/popen.rb",
|
||||
old_path: path,
|
||||
new_path: path,
|
||||
old_line: nil,
|
||||
new_line: line_number,
|
||||
diff_refs: diff_refs
|
||||
)
|
||||
end
|
||||
|
||||
factory :draft_note_on_image_diff do
|
||||
transient do
|
||||
path { "files/images/any_image.png" }
|
||||
end
|
||||
|
||||
position do
|
||||
association(:image_diff_position,
|
||||
file: path,
|
||||
diff_refs: diff_refs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
factory :draft_note_on_discussion, traits: [:on_discussion]
|
||||
|
|
|
|||
|
|
@ -86,6 +86,19 @@ RSpec.describe 'Merge request > Batch comments', :js do
|
|||
expect(page).to have_selector('.draft-note-component', text: 'Testing update')
|
||||
end
|
||||
|
||||
context 'with image and file draft note' do
|
||||
let(:merge_request) { create(:merge_request_with_diffs, :with_image_diffs, source_project: project) }
|
||||
let!(:draft_on_text) { create(:draft_note_on_text_diff, merge_request: merge_request, author: user, path: 'README.md', note: 'Lorem ipsum on text...') }
|
||||
let!(:draft_on_image) { create(:draft_note_on_image_diff, merge_request: merge_request, author: user, path: 'files/images/ee_repo_logo.png', note: 'Lorem ipsum on an image...') }
|
||||
|
||||
it 'does not show in overview' do
|
||||
visit_overview
|
||||
|
||||
expect(page).to have_no_text(draft_on_text.note)
|
||||
expect(page).to have_no_text(draft_on_image.note)
|
||||
end
|
||||
end
|
||||
|
||||
context 'adding single comment to review' do
|
||||
before do
|
||||
visit_overview
|
||||
|
|
|
|||
|
|
@ -408,10 +408,9 @@ describe('note_app', () => {
|
|||
store = createStore();
|
||||
store.registerModule('batchComments', batchComments());
|
||||
store.state.batchComments.drafts = [
|
||||
{ line_code: 1, isDraft: true },
|
||||
{ discussion_id: 1, isDraft: true },
|
||||
{ note: 'A', isDraft: true },
|
||||
{ note: 'B', isDraft: true },
|
||||
mockData.draftDiffDiscussion,
|
||||
mockData.draftReply,
|
||||
...mockData.draftComments,
|
||||
];
|
||||
store.state.isLoading = false;
|
||||
wrapper = shallowMount(NotesApp, {
|
||||
|
|
@ -426,10 +425,9 @@ describe('note_app', () => {
|
|||
it('correctly finds only draft comments', () => {
|
||||
const drafts = wrapper.findAll(DraftNote).wrappers;
|
||||
|
||||
expect(drafts.map((x) => x.props('draft'))).toEqual([
|
||||
expect.objectContaining({ note: 'A' }),
|
||||
expect.objectContaining({ note: 'B' }),
|
||||
]);
|
||||
expect(drafts.map((x) => x.props('draft'))).toEqual(
|
||||
mockData.draftComments.map(({ note }) => expect.objectContaining({ note })),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1273,10 +1273,16 @@ export const batchSuggestionsInfoMock = [
|
|||
];
|
||||
|
||||
export const draftComments = [
|
||||
{ id: 7, note: 'test draft note' },
|
||||
{ id: 9, note: 'draft note 2' },
|
||||
{ id: 7, note: 'test draft note', isDraft: true },
|
||||
{ id: 9, note: 'draft note 2', isDraft: true },
|
||||
];
|
||||
|
||||
export const draftReply = { id: 8, note: 'draft reply', discussion_id: 1 };
|
||||
export const draftReply = { id: 8, note: 'draft reply', discussion_id: 1, isDraft: true };
|
||||
|
||||
export const draftDiffDiscussion = { id: 6, note: 'draft diff discussion', line_code: 1 };
|
||||
export const draftDiffDiscussion = {
|
||||
id: 6,
|
||||
note: 'draft diff discussion',
|
||||
line_code: 1,
|
||||
file_path: 'lib/foo.rb',
|
||||
isDraft: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ RSpec.describe Gitlab::GitalyClient::BlobService do
|
|||
let(:limit) { 5 }
|
||||
let(:not_in) { %w[branch-a branch-b] }
|
||||
let(:expected_params) do
|
||||
{ revision: revision, limit: limit, not_in_refs: not_in, not_in_all: false }
|
||||
{ revisions: ["master", "--not", "branch-a", "branch-b"], limit: limit }
|
||||
end
|
||||
|
||||
subject { client.get_new_lfs_pointers(revision, limit, not_in) }
|
||||
|
||||
it 'sends a get_new_lfs_pointers message' do
|
||||
expect_any_instance_of(Gitaly::BlobService::Stub)
|
||||
.to receive(:get_new_lfs_pointers)
|
||||
.to receive(:list_lfs_pointers)
|
||||
.with(gitaly_request_with_params(expected_params), kind_of(Hash))
|
||||
.and_return([])
|
||||
|
||||
|
|
@ -31,12 +31,12 @@ RSpec.describe Gitlab::GitalyClient::BlobService do
|
|||
context 'with not_in = :all' do
|
||||
let(:not_in) { :all }
|
||||
let(:expected_params) do
|
||||
{ revision: revision, limit: limit, not_in_refs: [], not_in_all: true }
|
||||
{ revisions: ["master", "--not", "--all"], limit: limit }
|
||||
end
|
||||
|
||||
it 'sends the correct message' do
|
||||
expect_any_instance_of(Gitaly::BlobService::Stub)
|
||||
.to receive(:get_new_lfs_pointers)
|
||||
.to receive(:list_lfs_pointers)
|
||||
.with(gitaly_request_with_params(expected_params), kind_of(Hash))
|
||||
.and_return([])
|
||||
|
||||
|
|
@ -73,12 +73,16 @@ RSpec.describe Gitlab::GitalyClient::BlobService do
|
|||
end
|
||||
|
||||
describe '#get_all_lfs_pointers' do
|
||||
let(:expected_params) do
|
||||
{ revisions: ["--all"], limit: 0 }
|
||||
end
|
||||
|
||||
subject { client.get_all_lfs_pointers }
|
||||
|
||||
it 'sends a get_all_lfs_pointers message' do
|
||||
expect_any_instance_of(Gitaly::BlobService::Stub)
|
||||
.to receive(:get_all_lfs_pointers)
|
||||
.with(gitaly_request_with_params({}), kind_of(Hash))
|
||||
.to receive(:list_lfs_pointers)
|
||||
.with(gitaly_request_with_params(expected_params), kind_of(Hash))
|
||||
.and_return([])
|
||||
|
||||
subject
|
||||
|
|
|
|||
|
|
@ -94,4 +94,36 @@ RSpec.describe DeviseMailer do
|
|||
is_expected.to have_link(Gitlab.config.gitlab.url)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reset_password_instructions' do
|
||||
subject { described_class.reset_password_instructions(user, 'faketoken') }
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
it_behaves_like 'an email sent from GitLab'
|
||||
it_behaves_like 'it should not have Gmail Actions links'
|
||||
it_behaves_like 'a user cannot unsubscribe through footer link'
|
||||
|
||||
it 'is sent to the user' do
|
||||
is_expected.to deliver_to user.email
|
||||
end
|
||||
|
||||
it 'has the correct subject' do
|
||||
is_expected.to have_subject 'Reset password instructions'
|
||||
end
|
||||
|
||||
it 'greets the user' do
|
||||
is_expected.to have_body_text /Hello, #{user.name}!/
|
||||
end
|
||||
|
||||
it 'includes the correct content' do
|
||||
is_expected.to have_text /Someone, hopefully you, has requested to reset the password for your GitLab account on #{Gitlab.config.gitlab.url}/
|
||||
is_expected.to have_body_text /If you did not perform this request, you can safely ignore this email./
|
||||
is_expected.to have_body_text /Otherwise, click the link below to complete the process./
|
||||
end
|
||||
|
||||
it 'includes a link to reset the password' do
|
||||
is_expected.to have_link("Reset password", href: "#{Gitlab.config.gitlab.url}/users/password/edit?reset_password_token=faketoken")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,37 +4,12 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Issuable::DestroyService do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:group) { create(:group, :public) }
|
||||
let(:project) { create(:project, :public, group: group) }
|
||||
|
||||
subject(:service) { described_class.new(project, user) }
|
||||
|
||||
describe '#execute' do
|
||||
shared_examples_for 'service deleting todos' do
|
||||
it 'destroys associated todos asynchronously' do
|
||||
expect(TodosDestroyer::DestroyedIssuableWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
|
||||
subject.execute(issuable)
|
||||
end
|
||||
|
||||
context 'when destroy_issuable_todos_async feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(destroy_issuable_todos_async: false)
|
||||
end
|
||||
|
||||
it 'destroy associated todos synchronously' do
|
||||
expect_next_instance_of(TodosDestroyer::DestroyedIssuableWorker) do |worker|
|
||||
expect(worker)
|
||||
.to receive(:perform)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
end
|
||||
|
||||
subject.execute(issuable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when issuable is an issue' do
|
||||
let!(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container,
|
|||
subject { described_class.with_distribution(architecture.distribution) }
|
||||
|
||||
it 'does not return other distributions' do
|
||||
expect(subject.to_a).to eq([architecture, architecture_same_distribution])
|
||||
expect(subject.to_a).to match_array([architecture, architecture_same_distribution])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container,
|
|||
subject { described_class.with_name(architecture.name) }
|
||||
|
||||
it 'does not return other distributions' do
|
||||
expect(subject.to_a).to eq([architecture, architecture_same_name])
|
||||
expect(subject.to_a).to match_array([architecture, architecture_same_name])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ RSpec.shared_examples 'Debian Distribution Component' do |factory, container, ca
|
|||
subject { described_class.with_distribution(component.distribution) }
|
||||
|
||||
it 'does not return other distributions' do
|
||||
expect(subject.to_a).to eq([component, component_same_distribution])
|
||||
expect(subject.to_a).to match_array([component, component_same_distribution])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ RSpec.shared_examples 'Debian Distribution Component' do |factory, container, ca
|
|||
subject { described_class.with_name(component.name) }
|
||||
|
||||
it 'does not return other distributions' do
|
||||
expect(subject.to_a).to eq([component, component_same_name])
|
||||
expect(subject.to_a).to match_array([component, component_same_name])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
shared_examples_for 'service deleting todos' do
|
||||
before do
|
||||
stub_feature_flags(destroy_issuable_todos_async: group)
|
||||
end
|
||||
|
||||
it 'destroys associated todos asynchronously' do
|
||||
expect(TodosDestroyer::DestroyedIssuableWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
|
||||
subject.execute(issuable)
|
||||
end
|
||||
|
||||
context 'when destroy_issuable_todos_async feature is disabled for group' do
|
||||
before do
|
||||
stub_feature_flags(destroy_issuable_todos_async: false)
|
||||
end
|
||||
|
||||
it 'destroy associated todos synchronously' do
|
||||
expect_next_instance_of(TodosDestroyer::DestroyedIssuableWorker) do |worker|
|
||||
expect(worker)
|
||||
.to receive(:perform)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
end
|
||||
|
||||
subject.execute(issuable)
|
||||
end
|
||||
end
|
||||
end
|
||||