Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a158bebe03
commit
e8a31d8dc2
39 changed files with 420 additions and 59 deletions
|
@ -11,7 +11,6 @@ import { contentTop } from '~/lib/utils/common_utils';
|
|||
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
|
||||
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
|
||||
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
|
||||
export default {
|
||||
headerHeight: `${contentTop()}px`,
|
||||
|
@ -32,7 +31,17 @@ export default {
|
|||
SidebarIterationWidget: () =>
|
||||
import('ee_component/sidebar/components/sidebar_iteration_widget.vue'),
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: {
|
||||
epicFeatureAvailable: {
|
||||
default: false,
|
||||
},
|
||||
iterationFeatureAvailable: {
|
||||
default: false,
|
||||
},
|
||||
weightFeatureAvailable: {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isSidebarOpen',
|
||||
|
@ -77,10 +86,11 @@ export default {
|
|||
class="assignee"
|
||||
@assignees-updated="setAssignees"
|
||||
/>
|
||||
<board-sidebar-epic-select class="epic" />
|
||||
<board-sidebar-epic-select v-if="epicFeatureAvailable" class="epic" />
|
||||
<div>
|
||||
<board-sidebar-milestone-select />
|
||||
<sidebar-iteration-widget
|
||||
v-if="iterationFeatureAvailable"
|
||||
:iid="activeBoardItem.iid"
|
||||
:workspace-path="projectPathForActiveIssue"
|
||||
:iterations-workspace-path="groupPathForActiveIssue"
|
||||
|
@ -91,7 +101,7 @@ export default {
|
|||
<board-sidebar-time-tracker class="swimlanes-sidebar-time-tracker" />
|
||||
<board-sidebar-due-date />
|
||||
<board-sidebar-labels-select class="labels" />
|
||||
<board-sidebar-weight-input v-if="glFeatures.issueWeights" class="weight" />
|
||||
<board-sidebar-weight-input v-if="weightFeatureAvailable" class="weight" />
|
||||
<sidebar-confidentiality-widget
|
||||
:iid="activeBoardItem.iid"
|
||||
:full-path="fullPath"
|
||||
|
|
|
@ -101,6 +101,8 @@ export default () => {
|
|||
labelsManagePath: $boardApp.dataset.labelsManagePath,
|
||||
labelsFilterBasePath: $boardApp.dataset.labelsFilterBasePath,
|
||||
timeTrackingLimitToHours: parseBoolean($boardApp.dataset.timeTrackingLimitToHours),
|
||||
epicFeatureAvailable: parseBoolean($boardApp.dataset.epicFeatureAvailable),
|
||||
iterationFeatureAvailable: parseBoolean($boardApp.dataset.iterationFeatureAvailable),
|
||||
weightFeatureAvailable: parseBoolean($boardApp.dataset.weightFeatureAvailable),
|
||||
boardWeight: $boardApp.dataset.boardWeight
|
||||
? parseInt($boardApp.dataset.boardWeight, 10)
|
||||
|
|
|
@ -301,7 +301,7 @@ export default {
|
|||
<statistics-list v-else :counts="formattedCounts" />
|
||||
</div>
|
||||
<div v-if="!loading" class="col-md-6">
|
||||
<strong>{{ __('Duration for the last 30 commits') }}</strong>
|
||||
<strong>{{ __('Pipeline durations for the last 30 commits') }}</strong>
|
||||
<gl-column-chart
|
||||
:height="$options.chartContainerHeight"
|
||||
:option="$options.timesChartOptions"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { s__, __ } from '~/locale';
|
||||
|
||||
export const BRANCH_SUFFIX_COUNT = 8;
|
||||
export const DEFAULT_TARGET_BRANCH = 'master';
|
||||
export const ISSUABLE_TYPE = 'merge_request';
|
||||
|
||||
export const SUBMIT_CHANGES_BRANCH_ERROR = s__('StaticSiteEditor|Branch could not be created.');
|
||||
|
|
|
@ -9,6 +9,7 @@ const submitContentChangesResolver = (
|
|||
project: projectId,
|
||||
username,
|
||||
sourcePath,
|
||||
targetBranch,
|
||||
content,
|
||||
images,
|
||||
mergeRequestMeta,
|
||||
|
@ -21,6 +22,7 @@ const submitContentChangesResolver = (
|
|||
projectId,
|
||||
username,
|
||||
sourcePath,
|
||||
targetBranch,
|
||||
content,
|
||||
images,
|
||||
mergeRequestMeta,
|
||||
|
|
|
@ -111,6 +111,7 @@ export default {
|
|||
project: this.appData.project,
|
||||
username: this.appData.username,
|
||||
sourcePath: this.appData.sourcePath,
|
||||
targetBranch: this.appData.branch,
|
||||
content: this.content,
|
||||
formattedMarkdown: this.formattedMarkdown,
|
||||
images: this.images,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { BRANCH_SUFFIX_COUNT, DEFAULT_TARGET_BRANCH } from '../constants';
|
||||
import { BRANCH_SUFFIX_COUNT } from '../constants';
|
||||
|
||||
const generateBranchSuffix = () => `${Date.now()}`.substr(BRANCH_SUFFIX_COUNT);
|
||||
|
||||
const generateBranchName = (username, targetBranch = DEFAULT_TARGET_BRANCH) =>
|
||||
const generateBranchName = (username, targetBranch) =>
|
||||
`${username}-${targetBranch}-patch-${generateBranchSuffix()}`;
|
||||
|
||||
export default generateBranchName;
|
||||
|
|
|
@ -4,7 +4,6 @@ import generateBranchName from '~/static_site_editor/services/generate_branch_na
|
|||
import Tracking from '~/tracking';
|
||||
|
||||
import {
|
||||
DEFAULT_TARGET_BRANCH,
|
||||
SUBMIT_CHANGES_BRANCH_ERROR,
|
||||
SUBMIT_CHANGES_COMMIT_ERROR,
|
||||
SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
|
||||
|
@ -16,9 +15,9 @@ import {
|
|||
DEFAULT_FORMATTING_CHANGES_COMMIT_DESCRIPTION,
|
||||
} from '../constants';
|
||||
|
||||
const createBranch = (projectId, branch) =>
|
||||
const createBranch = (projectId, branch, targetBranch) =>
|
||||
Api.createBranch(projectId, {
|
||||
ref: DEFAULT_TARGET_BRANCH,
|
||||
ref: targetBranch,
|
||||
branch,
|
||||
}).catch(() => {
|
||||
throw new Error(SUBMIT_CHANGES_BRANCH_ERROR);
|
||||
|
@ -73,13 +72,7 @@ const commit = (projectId, message, branch, actions) => {
|
|||
});
|
||||
};
|
||||
|
||||
const createMergeRequest = (
|
||||
projectId,
|
||||
title,
|
||||
description,
|
||||
sourceBranch,
|
||||
targetBranch = DEFAULT_TARGET_BRANCH,
|
||||
) => {
|
||||
const createMergeRequest = (projectId, title, description, sourceBranch, targetBranch) => {
|
||||
Tracking.event(document.body.dataset.page, TRACKING_ACTION_CREATE_MERGE_REQUEST);
|
||||
Api.trackRedisCounterEvent(USAGE_PING_TRACKING_ACTION_CREATE_MERGE_REQUEST);
|
||||
|
||||
|
@ -100,16 +93,17 @@ const submitContentChanges = ({
|
|||
username,
|
||||
projectId,
|
||||
sourcePath,
|
||||
targetBranch,
|
||||
content,
|
||||
images,
|
||||
mergeRequestMeta,
|
||||
formattedMarkdown,
|
||||
}) => {
|
||||
const branch = generateBranchName(username);
|
||||
const branch = generateBranchName(username, targetBranch);
|
||||
const { title: mergeRequestTitle, description: mergeRequestDescription } = mergeRequestMeta;
|
||||
const meta = {};
|
||||
|
||||
return createBranch(projectId, branch)
|
||||
return createBranch(projectId, branch, targetBranch)
|
||||
.then(({ data: { web_url: url } }) => {
|
||||
const message = `${DEFAULT_FORMATTING_CHANGES_COMMIT_MESSAGE}\n\n${DEFAULT_FORMATTING_CHANGES_COMMIT_DESCRIPTION}`;
|
||||
|
||||
|
@ -133,7 +127,13 @@ const submitContentChanges = ({
|
|||
.then(({ data: { short_id: label, web_url: url } }) => {
|
||||
Object.assign(meta, { commit: { label, url } });
|
||||
|
||||
return createMergeRequest(projectId, mergeRequestTitle, mergeRequestDescription, branch);
|
||||
return createMergeRequest(
|
||||
projectId,
|
||||
mergeRequestTitle,
|
||||
mergeRequestDescription,
|
||||
branch,
|
||||
targetBranch,
|
||||
);
|
||||
})
|
||||
.then(({ data: { iid: label, web_url: url } }) => {
|
||||
Object.assign(meta, { mergeRequest: { label: label.toString(), url } });
|
||||
|
|
|
@ -22,6 +22,7 @@ class ApplicationController < ActionController::Base
|
|||
include Gitlab::Logging::CloudflareHelper
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include ::Gitlab::WithFeatureCategory
|
||||
include FlocOptOut
|
||||
|
||||
before_action :authenticate_user!, except: [:route_not_found]
|
||||
before_action :enforce_terms!, if: :should_enforce_terms?
|
||||
|
|
17
app/controllers/concerns/floc_opt_out.rb
Normal file
17
app/controllers/concerns/floc_opt_out.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module FlocOptOut
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_action :set_floc_opt_out_header, unless: :floc_enabled?
|
||||
end
|
||||
|
||||
def floc_enabled?
|
||||
Gitlab::CurrentSettings.floc_enabled
|
||||
end
|
||||
|
||||
def set_floc_opt_out_header
|
||||
response.headers['Permissions-Policy'] = 'interest-cohort=()'
|
||||
end
|
||||
end
|
|
@ -233,6 +233,7 @@ module ApplicationSettingsHelper
|
|||
:external_pipeline_validation_service_token,
|
||||
:external_pipeline_validation_service_url,
|
||||
:first_day_of_week,
|
||||
:floc_enabled,
|
||||
:force_pages_access_control,
|
||||
:gitaly_timeout_default,
|
||||
:gitaly_timeout_medium,
|
||||
|
|
|
@ -504,6 +504,9 @@ class ApplicationSetting < ApplicationRecord
|
|||
validates :whats_new_variant,
|
||||
inclusion: { in: ApplicationSetting.whats_new_variants.keys }
|
||||
|
||||
validates :floc_enabled,
|
||||
inclusion: { in: [true, false], message: _('must be a boolean value') }
|
||||
|
||||
attr_encrypted :asset_proxy_secret_key,
|
||||
mode: :per_attribute_iv,
|
||||
key: Settings.attr_encrypted_db_key_base_truncated,
|
||||
|
|
|
@ -77,6 +77,7 @@ module ApplicationSettingImplementation
|
|||
external_pipeline_validation_service_token: nil,
|
||||
external_pipeline_validation_service_url: nil,
|
||||
first_day_of_week: 0,
|
||||
floc_enabled: false,
|
||||
gitaly_timeout_default: 55,
|
||||
gitaly_timeout_fast: 10,
|
||||
gitaly_timeout_medium: 30,
|
||||
|
|
22
app/views/admin/application_settings/_floc.html.haml
Normal file
22
app/views/admin/application_settings/_floc.html.haml
Normal file
|
@ -0,0 +1,22 @@
|
|||
- expanded = integration_expanded?('floc_')
|
||||
|
||||
%section.settings.no-animate#js-floc-settings{ class: ('expanded' if expanded) }
|
||||
.settings-header
|
||||
%h4
|
||||
= s_('FloC|Federated Learning of Cohorts')
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
|
||||
= expanded ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= s_('FloC|Configure whether you want to participate in FloC.').html_safe
|
||||
= link_to sprite_icon('question-o'), 'https://github.com/WICG/floc', target: '_blank', class: 'has-tooltip', title: _('More information')
|
||||
|
||||
.settings-content
|
||||
= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-floc-settings'), html: { class: 'fieldset-form', id: 'floc-settings' } do |f|
|
||||
= form_errors(@application_setting)
|
||||
|
||||
%fieldset
|
||||
.form-group
|
||||
.form-check
|
||||
= f.check_box :floc_enabled, class: 'form-check-input'
|
||||
= f.label :floc_enabled, s_('FloC|Enable FloC (Federated Learning of Cohorts)'), class: 'form-check-label'
|
||||
= f.submit s_('Save changes'), class: 'gl-button btn btn-confirm'
|
|
@ -112,3 +112,4 @@
|
|||
= render 'admin/application_settings/third_party_offers'
|
||||
= render 'admin/application_settings/snowplow'
|
||||
= render 'admin/application_settings/eks'
|
||||
= render 'admin/application_settings/floc'
|
||||
|
|
5
changelogs/unreleased/32107-delete-package-file-api.yml
Normal file
5
changelogs/unreleased/32107-delete-package-file-api.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add API endpoint for deleting a package file
|
||||
merge_request: 60970
|
||||
author:
|
||||
type: added
|
5
changelogs/unreleased/leipert-floc-opt-out-327904.yml
Normal file
5
changelogs/unreleased/leipert-floc-opt-out-327904.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Application setting for FloC participation (disabled by default)
|
||||
merge_request: 60933
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: track_epic_boards_activity
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60357
|
||||
rollout_issue_url:
|
||||
milestone: '13.12'
|
||||
type: development
|
||||
group: group::product planning
|
||||
default_enabled: true
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFlocApplicationSettings < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :application_settings, :floc_enabled, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
1
db/schema_migrations/20210504135823
Normal file
1
db/schema_migrations/20210504135823
Normal file
|
@ -0,0 +1 @@
|
|||
9d1254393da80e0b1e387fba493f83f8775f0340f23c648e638a9983f965f5c9
|
|
@ -9513,6 +9513,7 @@ CREATE TABLE application_settings (
|
|||
whats_new_variant smallint DEFAULT 0,
|
||||
encrypted_spam_check_api_key bytea,
|
||||
encrypted_spam_check_api_key_iv bytea,
|
||||
floc_enabled boolean DEFAULT false NOT NULL,
|
||||
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
|
||||
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
|
||||
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
|
||||
|
|
|
@ -352,3 +352,33 @@ Can return the following status codes:
|
|||
|
||||
- `204 No Content`, if the package was deleted successfully.
|
||||
- `404 Not Found`, if the package was not found.
|
||||
|
||||
## Delete a package file
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32107) in GitLab 13.12.
|
||||
|
||||
WARNING:
|
||||
Deleting a package file may corrupt your package making it unusable or unpullable from your package
|
||||
manager client. When deleting a package file, be sure that you understand what you're doing.
|
||||
|
||||
Delete a package file:
|
||||
|
||||
```plaintext
|
||||
DELETE /projects/:id/packages/:package_id/package_files/:package_file_id
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ----------------- | -------------- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
|
||||
| `package_id` | integer | yes | ID of a package. |
|
||||
| `package_file_id` | integer | yes | ID of a package file. |
|
||||
|
||||
```shell
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages/:package_id/package_files/:package_file_id"
|
||||
```
|
||||
|
||||
Can return the following status codes:
|
||||
|
||||
- `204 No Content`: The package was deleted successfully.
|
||||
- `403 Forbidden`: The user does not have permission to delete the file.
|
||||
- `404 Not Found`: The package or package file was not found.
|
||||
|
|
|
@ -88,6 +88,7 @@ Example response:
|
|||
"rate_limiting_response_text": null,
|
||||
"keep_latest_artifact": true,
|
||||
"admin_mode": false,
|
||||
"floc_enabled": false,
|
||||
"external_pipeline_validation_service_timeout": null,
|
||||
"external_pipeline_validation_service_token": null,
|
||||
"external_pipeline_validation_service_url": null
|
||||
|
|
|
@ -10234,6 +10234,78 @@ Status: `data_available`
|
|||
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_creating_epic_boards_monthly`
|
||||
|
||||
Count of MAU creating epic boards
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210428072511_g_project_management_users_creating_epic_boards_monthly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_creating_epic_boards_weekly`
|
||||
|
||||
Count of WAU creating epic boards
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210428072508_g_project_management_users_creating_epic_boards_weekly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_updating_epic_board_names_monthly`
|
||||
|
||||
Count of MAU updating epic board names
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210428073607_g_project_management_users_updating_epic_board_names_monthly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_updating_epic_board_names_weekly`
|
||||
|
||||
Count of WAU updating epic board names
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210428073604_g_project_management_users_updating_epic_board_names_weekly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_viewing_epic_boards_monthly`
|
||||
|
||||
Count of MAU viewing epic boards
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210428073329_g_project_management_users_viewing_epic_boards_monthly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epic_boards_usage.g_project_management_users_viewing_epic_boards_weekly`
|
||||
|
||||
Count of WAU viewing epic boards
|
||||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210428073327_g_project_management_users_viewing_epic_boards_weekly.yml)
|
||||
|
||||
Group: `group::product planning`
|
||||
|
||||
Status: `implemented`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
### `redis_hll_counters.epics_usage.epics_usage_total_unique_counts_monthly`
|
||||
|
||||
Total monthly users count for epics_usage
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 22 KiB |
|
@ -92,11 +92,11 @@ Please note that the certificate [fingerprint algorithm](../../../integration/sa
|
|||
|
||||
### SSO enforcement
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) in GitLab 11.8.
|
||||
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI.
|
||||
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience.
|
||||
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO.
|
||||
- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) in GitLab 11.8.
|
||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI.
|
||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience.
|
||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO.
|
||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9152) in GitLab 13.11 with enforcing open SSO session to use Git if this setting is switched on.
|
||||
|
||||
With this option enabled, users (except owners) must go through your group's GitLab single sign-on URL if they wish to access group resources through the UI. Users can't be manually added as members.
|
||||
|
||||
|
|
|
@ -30,6 +30,29 @@ module API
|
|||
|
||||
present paginate(package.package_files), with: ::API::Entities::PackageFile
|
||||
end
|
||||
|
||||
desc 'Remove a package file' do
|
||||
detail 'This feature was introduced in GitLab 13.12'
|
||||
end
|
||||
params do
|
||||
requires :package_file_id, type: Integer, desc: 'The ID of a package file'
|
||||
end
|
||||
delete ':id/packages/:package_id/package_files/:package_file_id' do
|
||||
authorize_destroy_package!(user_project)
|
||||
|
||||
# We want to make sure the file belongs to the declared package
|
||||
# so we look up the package before looking up the file.
|
||||
package = ::Packages::PackageFinder
|
||||
.new(user_project, params[:package_id]).execute
|
||||
|
||||
not_found! unless package
|
||||
|
||||
package_file = package.package_files.find_by_id(params[:package_file_id])
|
||||
|
||||
not_found! unless package_file
|
||||
|
||||
destroy_conditionally!(package_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -171,6 +171,7 @@ module API
|
|||
optional :wiki_page_max_content_bytes, type: Integer, desc: "Maximum wiki page content size in bytes"
|
||||
optional :require_admin_approval_after_user_signup, type: Boolean, desc: 'Require explicit admin approval for new signups'
|
||||
optional :whats_new_variant, type: String, values: ApplicationSetting.whats_new_variants.keys, desc: "What's new variant, possible values: `all_tiers`, `current_tier`, and `disabled`."
|
||||
optional :floc_enabled, type: Grape::API::Boolean, desc: 'Enable FloC (Federated Learning of Cohorts)'
|
||||
|
||||
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
|
||||
optional :"#{type}_key_restriction",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# Epic board events
|
||||
#
|
||||
# We are using the same slot of issue events 'project_management' for
|
||||
# epic events to allow data aggregation.
|
||||
# More information in: https://gitlab.com/gitlab-org/gitlab/-/issues/322405
|
||||
- name: g_project_management_users_creating_epic_boards
|
||||
category: epic_boards_usage
|
||||
redis_slot: project_management
|
||||
aggregation: daily
|
||||
feature_flag: track_epic_boards_activity
|
||||
|
||||
- name: g_project_management_users_viewing_epic_boards
|
||||
category: epic_boards_usage
|
||||
redis_slot: project_management
|
||||
aggregation: daily
|
||||
feature_flag: track_epic_boards_activity
|
||||
|
||||
- name: g_project_management_users_updating_epic_board_names
|
||||
category: epic_boards_usage
|
||||
redis_slot: project_management
|
||||
aggregation: daily
|
||||
feature_flag: track_epic_boards_activity
|
|
@ -11738,9 +11738,6 @@ msgstr ""
|
|||
msgid "Duration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Duration for the last 30 commits"
|
||||
msgstr ""
|
||||
|
||||
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
|
||||
msgstr ""
|
||||
|
||||
|
@ -14097,6 +14094,15 @@ msgstr ""
|
|||
msgid "Flags"
|
||||
msgstr ""
|
||||
|
||||
msgid "FloC|Configure whether you want to participate in FloC."
|
||||
msgstr ""
|
||||
|
||||
msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
|
||||
msgstr ""
|
||||
|
||||
msgid "FloC|Federated Learning of Cohorts"
|
||||
msgstr ""
|
||||
|
||||
msgid "FlowdockService|1b609b52537..."
|
||||
msgstr ""
|
||||
|
||||
|
@ -14856,10 +14862,10 @@ msgstr ""
|
|||
msgid "Geo|Verification failed - %{error}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Geo|Verification status"
|
||||
msgid "Geo|Verification information"
|
||||
msgstr ""
|
||||
|
||||
msgid "Geo|Verificaton information"
|
||||
msgid "Geo|Verification status"
|
||||
msgstr ""
|
||||
|
||||
msgid "Geo|Waiting for scheduler"
|
||||
|
@ -23668,6 +23674,9 @@ msgstr ""
|
|||
msgid "Pipeline Schedules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pipeline durations for the last 30 commits"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pipeline minutes quota"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1027,4 +1027,44 @@ RSpec.describe ApplicationController do
|
|||
get :index
|
||||
end
|
||||
end
|
||||
|
||||
describe 'setting permissions-policy header' do
|
||||
controller do
|
||||
skip_before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
render html: 'It is a flock of sheep, not a floc of sheep.'
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
routes.draw do
|
||||
get 'index' => 'anonymous#index'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with FloC enabled' do
|
||||
before do
|
||||
stub_application_setting floc_enabled: true
|
||||
end
|
||||
|
||||
it 'does not set the Permissions-Policy header' do
|
||||
get :index
|
||||
|
||||
expect(response.headers['Permissions-Policy']).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with FloC disabled' do
|
||||
before do
|
||||
stub_application_setting floc_enabled: false
|
||||
end
|
||||
|
||||
it 'sets the Permissions-Policy header' do
|
||||
get :index
|
||||
|
||||
expect(response.headers['Permissions-Policy']).to eq('interest-cohort=()')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,7 +75,7 @@ RSpec.describe 'Project Graph', :js do
|
|||
expect(page).to have_content 'Last week'
|
||||
expect(page).to have_content 'Last month'
|
||||
expect(page).to have_content 'Last year'
|
||||
expect(page).to have_content 'Duration for the last 30 commits'
|
||||
expect(page).to have_content 'Pipeline durations for the last 30 commits'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,7 +55,7 @@ export const mergeRequestTemplates = [
|
|||
|
||||
export const submitChangesError = 'Could not save changes';
|
||||
export const commitBranchResponse = {
|
||||
web_url: '/tree/root-master-patch-88195',
|
||||
web_url: '/tree/root-main-patch-88195',
|
||||
};
|
||||
export const commitMultipleResponse = {
|
||||
short_id: 'ed899a2f4b5',
|
||||
|
@ -84,8 +84,8 @@ export const mounts = [
|
|||
},
|
||||
];
|
||||
|
||||
export const branch = 'master';
|
||||
export const branch = 'main';
|
||||
|
||||
export const baseUrl = '/user1/project1/-/sse/master%2Ftest.md';
|
||||
export const baseUrl = '/user1/project1/-/sse/main%2Ftest.md';
|
||||
|
||||
export const imageRoot = 'source/images/';
|
||||
|
|
|
@ -275,6 +275,7 @@ describe('static_site_editor/pages/home', () => {
|
|||
formattedMarkdown,
|
||||
project,
|
||||
sourcePath,
|
||||
targetBranch: branch,
|
||||
username,
|
||||
images,
|
||||
mergeRequestMeta,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DEFAULT_TARGET_BRANCH, BRANCH_SUFFIX_COUNT } from '~/static_site_editor/constants';
|
||||
import { BRANCH_SUFFIX_COUNT } from '~/static_site_editor/constants';
|
||||
import generateBranchName from '~/static_site_editor/services/generate_branch_name';
|
||||
|
||||
import { username } from '../mock_data';
|
||||
import { username, branch as targetBranch } from '../mock_data';
|
||||
|
||||
describe('generateBranchName', () => {
|
||||
const timestamp = 12345678901234;
|
||||
|
@ -11,11 +11,11 @@ describe('generateBranchName', () => {
|
|||
});
|
||||
|
||||
it('generates a name that includes the username and target branch', () => {
|
||||
expect(generateBranchName(username)).toMatch(`${username}-${DEFAULT_TARGET_BRANCH}`);
|
||||
expect(generateBranchName(username, targetBranch)).toMatch(`${username}-${targetBranch}`);
|
||||
});
|
||||
|
||||
it(`adds the first ${BRANCH_SUFFIX_COUNT} numbers of the current timestamp`, () => {
|
||||
expect(generateBranchName(username)).toMatch(
|
||||
expect(generateBranchName(username, targetBranch)).toMatch(
|
||||
timestamp.toString().substring(BRANCH_SUFFIX_COUNT),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -47,11 +47,11 @@ describe('rich_content_editor/renderers/render_image', () => {
|
|||
it.each`
|
||||
destination | isAbsolute | src
|
||||
${'http://test.host/absolute/path/to/image.png'} | ${true} | ${'http://test.host/absolute/path/to/image.png'}
|
||||
${'/relative/path/to/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/default/source/relative/path/to/image.png'}
|
||||
${'/target/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/source/with/target/image.png'}
|
||||
${'relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/relative/to/current/image.png'}
|
||||
${'./relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/./relative/to/current/image.png'}
|
||||
${'../relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/master/../relative/to/current/image.png'}
|
||||
${'/relative/path/to/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/main/default/source/relative/path/to/image.png'}
|
||||
${'/target/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/main/source/with/target/image.png'}
|
||||
${'relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/main/relative/to/current/image.png'}
|
||||
${'./relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/main/./relative/to/current/image.png'}
|
||||
${'../relative/to/current/image.png'} | ${false} | ${'http://test.host/user1/project1/-/raw/main/../relative/to/current/image.png'}
|
||||
`('returns an image with the correct attributes', ({ destination, isAbsolute, src }) => {
|
||||
node.destination = destination;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import Api from '~/api';
|
|||
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
|
||||
|
||||
import {
|
||||
DEFAULT_TARGET_BRANCH,
|
||||
SUBMIT_CHANGES_BRANCH_ERROR,
|
||||
SUBMIT_CHANGES_COMMIT_ERROR,
|
||||
SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
|
||||
|
@ -25,6 +24,7 @@ import {
|
|||
createMergeRequestResponse,
|
||||
mergeRequestMeta,
|
||||
sourcePath,
|
||||
branch as targetBranch,
|
||||
sourceContentYAML as content,
|
||||
trackingCategory,
|
||||
images,
|
||||
|
@ -33,7 +33,7 @@ import {
|
|||
jest.mock('~/static_site_editor/services/generate_branch_name');
|
||||
|
||||
describe('submitContentChanges', () => {
|
||||
const branch = 'branch-name';
|
||||
const sourceBranch = 'branch-name';
|
||||
let trackingSpy;
|
||||
let origPage;
|
||||
|
||||
|
@ -41,6 +41,7 @@ describe('submitContentChanges', () => {
|
|||
username,
|
||||
projectId,
|
||||
sourcePath,
|
||||
targetBranch,
|
||||
content,
|
||||
images,
|
||||
mergeRequestMeta,
|
||||
|
@ -54,7 +55,7 @@ describe('submitContentChanges', () => {
|
|||
.spyOn(Api, 'createProjectMergeRequest')
|
||||
.mockResolvedValue({ data: createMergeRequestResponse });
|
||||
|
||||
generateBranchName.mockReturnValue(branch);
|
||||
generateBranchName.mockReturnValue(sourceBranch);
|
||||
|
||||
origPage = document.body.dataset.page;
|
||||
document.body.dataset.page = trackingCategory;
|
||||
|
@ -69,8 +70,8 @@ describe('submitContentChanges', () => {
|
|||
it('creates a branch named after the username and target branch', () => {
|
||||
return submitContentChanges(buildPayload()).then(() => {
|
||||
expect(Api.createBranch).toHaveBeenCalledWith(projectId, {
|
||||
ref: DEFAULT_TARGET_BRANCH,
|
||||
branch,
|
||||
ref: targetBranch,
|
||||
branch: sourceBranch,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -86,7 +87,7 @@ describe('submitContentChanges', () => {
|
|||
describe('committing markdown formatting changes', () => {
|
||||
const formattedMarkdown = `formatted ${content}`;
|
||||
const commitPayload = {
|
||||
branch,
|
||||
branch: sourceBranch,
|
||||
commit_message: `${DEFAULT_FORMATTING_CHANGES_COMMIT_MESSAGE}\n\n${DEFAULT_FORMATTING_CHANGES_COMMIT_DESCRIPTION}`,
|
||||
actions: [
|
||||
{
|
||||
|
@ -116,7 +117,7 @@ describe('submitContentChanges', () => {
|
|||
it('commits the content changes to the branch when creating branch succeeds', () => {
|
||||
return submitContentChanges(buildPayload()).then(() => {
|
||||
expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, {
|
||||
branch,
|
||||
branch: sourceBranch,
|
||||
commit_message: mergeRequestMeta.title,
|
||||
actions: [
|
||||
{
|
||||
|
@ -140,7 +141,7 @@ describe('submitContentChanges', () => {
|
|||
const payload = buildPayload({ content: contentWithoutImages });
|
||||
return submitContentChanges(payload).then(() => {
|
||||
expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, {
|
||||
branch,
|
||||
branch: sourceBranch,
|
||||
commit_message: mergeRequestMeta.title,
|
||||
actions: [
|
||||
{
|
||||
|
@ -169,8 +170,8 @@ describe('submitContentChanges', () => {
|
|||
convertObjectPropsToSnakeCase({
|
||||
title,
|
||||
description,
|
||||
targetBranch: DEFAULT_TARGET_BRANCH,
|
||||
sourceBranch: branch,
|
||||
targetBranch,
|
||||
sourceBranch,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
@ -194,7 +195,7 @@ describe('submitContentChanges', () => {
|
|||
});
|
||||
|
||||
it('returns the branch name', () => {
|
||||
expect(result).toMatchObject({ branch: { label: branch } });
|
||||
expect(result).toMatchObject({ branch: { label: sourceBranch } });
|
||||
});
|
||||
|
||||
it('returns commit short id and web url', () => {
|
||||
|
|
|
@ -45,6 +45,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
'quickactions',
|
||||
'pipeline_authoring',
|
||||
'epics_usage',
|
||||
'epic_boards_usage',
|
||||
'secure'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -7,13 +7,13 @@ RSpec.describe API::PackageFiles do
|
|||
let(:project) { create(:project, :public) }
|
||||
let(:package) { create(:maven_package, project: project) }
|
||||
|
||||
before do
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/packages/:package_id/package_files' do
|
||||
let(:url) { "/projects/#{project.id}/packages/#{package.id}/package_files" }
|
||||
|
||||
before do
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
context 'without the need for a license' do
|
||||
context 'project is public' do
|
||||
it 'returns 200' do
|
||||
|
@ -78,4 +78,77 @@ RSpec.describe API::PackageFiles do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /projects/:id/packages/:package_id/package_files/:package_file_id' do
|
||||
let(:package_file_id) { package.package_files.first.id }
|
||||
let(:url) { "/projects/#{project.id}/packages/#{package.id}/package_files/#{package_file_id}" }
|
||||
|
||||
subject(:api_request) { delete api(url, user) }
|
||||
|
||||
context 'project is public' do
|
||||
context 'without user' do
|
||||
let(:user) { nil }
|
||||
|
||||
it 'returns 403 for non authenticated user', :aggregate_failures do
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 403 for a user without access to the project', :aggregate_failures do
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context 'project is private' do
|
||||
let_it_be_with_refind(:project) { create(:project, :private) }
|
||||
|
||||
it 'returns 404 for a user without access to the project', :aggregate_failures do
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
|
||||
it 'returns 403 for a user without enough permissions', :aggregate_failures do
|
||||
project.add_developer(user)
|
||||
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
|
||||
it 'returns 204', :aggregate_failures do
|
||||
project.add_maintainer(user)
|
||||
|
||||
expect { api_request }.to change { package.package_files.count }.by(-1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
|
||||
context 'without user' do
|
||||
let(:user) { nil }
|
||||
|
||||
it 'returns 404 for non authenticated user', :aggregate_failures do
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid file' do
|
||||
let(:url) { "/projects/#{project.id}/packages/#{package.id}/package_files/999999" }
|
||||
|
||||
it 'returns 404 when the package file does not exist', :aggregate_failures do
|
||||
project.add_maintainer(user)
|
||||
|
||||
expect { api_request }.not_to change { package.package_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue