Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
58c42f2f45
commit
3a5bee7879
26 changed files with 327 additions and 78 deletions
2
Gemfile
2
Gemfile
|
@ -246,7 +246,7 @@ gem 're2', '~> 1.6.0'
|
|||
gem 'version_sorter', '~> 2.2.4'
|
||||
|
||||
# Export Ruby Regex to Javascript
|
||||
gem 'js_regex', '~> 3.7'
|
||||
gem 'js_regex', '~> 3.8'
|
||||
|
||||
# User agent parsing
|
||||
gem 'device_detector'
|
||||
|
|
|
@ -286,7 +286,7 @@
|
|||
{"name":"jaro_winkler","version":"1.5.4","platform":"ruby","checksum":"50c3e83c5a9e8769c1cf5b73c8b51bb6eebbf8852a0ee53bf6ad6e4dc63414f9"},
|
||||
{"name":"jira-ruby","version":"2.1.4","platform":"ruby","checksum":"4267c095cac8323b9eef3ba866eb28bb1388b7623a5abb60c1e7caf12d4adb9e"},
|
||||
{"name":"jmespath","version":"1.6.1","platform":"ruby","checksum":"40ca83f4141bdd1e503db5485de68b84237183d84cf7a159fbeebcc6005adbd6"},
|
||||
{"name":"js_regex","version":"3.7.0","platform":"ruby","checksum":"b13fac68c4416d1a5f21c3bab8a71b4530f424b7c4ff9f46d8e62b895dc05975"},
|
||||
{"name":"js_regex","version":"3.8.0","platform":"ruby","checksum":"7934bcdd5a0e6d5af4a520288fd4684a02a472ae55831d9178ccaf82356344b5"},
|
||||
{"name":"json","version":"2.5.1","platform":"java","checksum":"be284a0c4a9d0373e81b0d5dfe71ed5b18d0479f05970e60a77be89a2978ce6c"},
|
||||
{"name":"json","version":"2.5.1","platform":"ruby","checksum":"918d8c41dacb7cfdbe0c7bbd6014a5372f0cf1c454ca150e9f4010fe80cc3153"},
|
||||
{"name":"json-jwt","version":"1.15.3","platform":"ruby","checksum":"66db4f14e538a774c15502a5b5b26b1f3e7585481bbb96df490aa74b5c2d6110"},
|
||||
|
|
|
@ -758,9 +758,9 @@ GEM
|
|||
multipart-post
|
||||
oauth (~> 0.5, >= 0.5.0)
|
||||
jmespath (1.6.1)
|
||||
js_regex (3.7.0)
|
||||
js_regex (3.8.0)
|
||||
character_set (~> 1.4)
|
||||
regexp_parser (~> 2.1)
|
||||
regexp_parser (~> 2.5)
|
||||
regexp_property_values (~> 1.0)
|
||||
json (2.5.1)
|
||||
json-jwt (1.15.3)
|
||||
|
@ -1673,7 +1673,7 @@ DEPENDENCIES
|
|||
ipaddress (~> 0.8.3)
|
||||
ipynbdiff!
|
||||
jira-ruby (~> 2.1.4)
|
||||
js_regex (~> 3.7)
|
||||
js_regex (~> 3.8)
|
||||
json (~> 2.5.1)
|
||||
json_schemer (~> 0.2.18)
|
||||
jwt (~> 2.1.0)
|
||||
|
|
|
@ -85,10 +85,12 @@ export const billingPlanNames = {
|
|||
};
|
||||
|
||||
const INTEGRATION_TYPE_SLACK = 'slack';
|
||||
const INTEGRATION_TYPE_SLACK_APPLICATION = 'gitlab_slack_application';
|
||||
const INTEGRATION_TYPE_MATTERMOST = 'mattermost';
|
||||
|
||||
export const placeholderForType = {
|
||||
[INTEGRATION_TYPE_SLACK]: __('#general, #development'),
|
||||
[INTEGRATION_TYPE_SLACK_APPLICATION]: __('#general, #development'),
|
||||
[INTEGRATION_TYPE_MATTERMOST]: __('my-channel'),
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapGetters(['isInheriting']),
|
||||
placeholder() {
|
||||
defaultPlaceholder() {
|
||||
return placeholderForType[this.type];
|
||||
},
|
||||
},
|
||||
|
@ -55,7 +55,7 @@ export default {
|
|||
v-if="event.field"
|
||||
v-model="event.field.value"
|
||||
:name="fieldName(event.field.name)"
|
||||
:placeholder="placeholder"
|
||||
:placeholder="event.field.placeholder || defaultPlaceholder"
|
||||
:readonly="isInheriting"
|
||||
/>
|
||||
</gl-form-group>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
s_('ProjectSettings|Skipped pipelines are considered successful'),
|
||||
help_text: s_('ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline.'),
|
||||
checkbox_options: { class: 'gl-pl-6' }
|
||||
= render_if_exists 'projects/merge_request_merge_checks_status_checks', form: form, project: @project
|
||||
= form.gitlab_ui_checkbox_component :only_allow_merge_if_all_discussions_are_resolved,
|
||||
s_('ProjectSettings|All threads must be resolved'),
|
||||
checkbox_options: { data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' } }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: integration_slack_app_notifications
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98663
|
||||
rollout_issue_url:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/381012
|
||||
milestone: '15.5'
|
||||
type: development
|
||||
group: group::integrations
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Currently we register validator only for `dev` or `test` environment
|
||||
Gitlab::Database::QueryAnalyzer.instance.hook!
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(
|
||||
::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification
|
||||
)
|
||||
Gitlab::Database::QueryAnalyzer.instance.tap do |query_analyzer|
|
||||
query_analyzer.hook!
|
||||
|
||||
if Gitlab.dev_or_test_env?
|
||||
query_analyzer = ::Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(query_analyzer)
|
||||
query_analyzer.all_analyzers.tap do |analyzers|
|
||||
analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
|
||||
analyzers.append(::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification)
|
||||
|
||||
if Gitlab.dev_or_test_env?
|
||||
analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection)
|
||||
analyzers.append(::Gitlab::Database::QueryAnalyzers::QueryRecorder)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Application.configure do |config|
|
||||
|
|
|
@ -26,6 +26,10 @@ metadata:
|
|||
description: Operations related to deploy tokens
|
||||
- name: deployments
|
||||
description: Operations related to deployments
|
||||
- name: environments
|
||||
description: Operations related to environments
|
||||
- name: feature_flags_user_lists
|
||||
description: Operations related to accessing GitLab feature flag user lists
|
||||
- name: features
|
||||
description: Operations related to managing Flipper-based feature flags
|
||||
- name: freeze_periods
|
||||
|
|
|
@ -20,7 +20,7 @@ GET /projects/:id/environments
|
|||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `name` | string | no | Return the environment with this name. Mutually exclusive with `search` |
|
||||
| `search` | string | no | Return list of environments matching the search criteria. Mutually exclusive with `name` |
|
||||
| `states` | string | no | List all environments that match a specific state. Accepted values: `available`, `stopping` or `stopped`. If no state value given, returns all environments. |
|
||||
| `states` | string | no | List all environments that match a specific state. Accepted values: `available`, `stopping`, or `stopped`. If no state value given, returns all environments. |
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments?name=review%2Ffix-foo"
|
||||
|
@ -279,7 +279,7 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
## Edit an existing environment
|
||||
## Update an existing environment
|
||||
|
||||
Updates an existing environment's name and/or `external_url`.
|
||||
|
||||
|
|
|
@ -107,6 +107,33 @@ job:
|
|||
- make build
|
||||
```
|
||||
|
||||
#### Skip job if the branch is empty
|
||||
|
||||
Use [`rules:changes:compare_to`](../yaml/index.md#ruleschangescompare_to) to avoid
|
||||
running a job when the branch is empty, which saves CI/CD resources. Compare the
|
||||
branch to the default branch, and if the branch:
|
||||
|
||||
- Doesn't have changed files, the job doesn't run.
|
||||
- Has changed files, the job runs.
|
||||
|
||||
For example, in a project with `main` as the default branch:
|
||||
|
||||
```yaml
|
||||
job:
|
||||
script:
|
||||
- echo "This job only runs for branches that are not empty"
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
changes:
|
||||
compare_to: refs/heads/main
|
||||
paths:
|
||||
- '*'
|
||||
```
|
||||
|
||||
The rule for this job compares all files and paths (`*`) in the current branch against
|
||||
the default branch `main`. The rule matches and the job runs only when there are
|
||||
changes to the files in the branch.
|
||||
|
||||
### Complex rules
|
||||
|
||||
You can use all `rules` keywords, like `if`, `changes`, and `exists`, in the same
|
||||
|
|
|
@ -1155,7 +1155,7 @@ that use the same cache key use the same cache, including in different pipelines
|
|||
If not set, the default key is `default`. All jobs with the `cache` keyword but
|
||||
no `cache:key` share the `default` cache.
|
||||
|
||||
Must be used with `cache: path`, or nothing is cached.
|
||||
Must be used with `cache: paths`, or nothing is cached.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job or in the
|
||||
[`default` section](#default).
|
||||
|
@ -1325,7 +1325,7 @@ rspec:
|
|||
|
||||
Use `cache:when` to define when to save the cache, based on the status of the job.
|
||||
|
||||
Must be used with `cache: path`, or nothing is cached.
|
||||
Must be used with `cache: paths`, or nothing is cached.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job or in the
|
||||
[`default` section](#default).
|
||||
|
@ -1365,7 +1365,7 @@ Use the `pull` policy when you have many jobs executing in parallel that use the
|
|||
This policy speeds up job execution and reduces load on the cache server. You can
|
||||
use a job with the `push` policy to build the cache.
|
||||
|
||||
Must be used with `cache: path`, or nothing is cached.
|
||||
Must be used with `cache: paths`, or nothing is cached.
|
||||
|
||||
**Keyword type**: Job keyword. You can use it only as part of a job or in the
|
||||
[`default` section](#default).
|
||||
|
@ -1773,7 +1773,7 @@ deploy:
|
|||
**Additional details**:
|
||||
|
||||
- Enviroments created from this job definition are assigned a [tier](../environments/index.md#deployment-tier-of-environments) based on this value.
|
||||
- Existing environments don't have their tier updated if this value is added later. Existing enviroments must have their tier updated via the [Environments API](../../api/environments.md#edit-an-existing-environment).
|
||||
- Existing environments don't have their tier updated if this value is added later. Existing enviroments must have their tier updated via the [Environments API](../../api/environments.md#update-an-existing-environment).
|
||||
|
||||
**Related topics**:
|
||||
|
||||
|
|
|
@ -176,6 +176,8 @@ module API
|
|||
mount ::API::DeployKeys
|
||||
mount ::API::DeployTokens
|
||||
mount ::API::Deployments
|
||||
mount ::API::Environments
|
||||
mount ::API::FeatureFlagsUserLists
|
||||
mount ::API::Features
|
||||
mount ::API::FreezePeriods
|
||||
mount ::API::Metadata
|
||||
|
@ -225,13 +227,11 @@ module API
|
|||
mount ::API::DebianProjectPackages
|
||||
mount ::API::DependencyProxy
|
||||
mount ::API::Discussions
|
||||
mount ::API::Environments
|
||||
mount ::API::ErrorTracking::ClientKeys
|
||||
mount ::API::ErrorTracking::Collector
|
||||
mount ::API::ErrorTracking::ProjectSettings
|
||||
mount ::API::Events
|
||||
mount ::API::FeatureFlags
|
||||
mount ::API::FeatureFlagsUserLists
|
||||
mount ::API::Files
|
||||
mount ::API::GenericPackages
|
||||
mount ::API::Geo
|
||||
|
|
|
@ -5,10 +5,10 @@ module API
|
|||
class Environment < Entities::EnvironmentBasic
|
||||
include RequestAwareEntity
|
||||
|
||||
expose :tier
|
||||
expose :tier, documentation: { type: 'string', example: 'development' }
|
||||
expose :project, using: Entities::BasicProjectDetails
|
||||
expose :last_deployment, using: Entities::Deployment, if: { last_deployment: true }
|
||||
expose :state
|
||||
expose :state, documentation: { type: 'string', example: 'available' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
module API
|
||||
module Entities
|
||||
class EnvironmentBasic < Grape::Entity
|
||||
expose :id, :name, :slug, :external_url, :created_at, :updated_at
|
||||
expose :id, documentation: { type: 'integer', example: 1 }
|
||||
expose :name, documentation: { type: 'string', example: 'deploy' }
|
||||
expose :slug, documentation: { type: 'string', example: 'deploy' }
|
||||
expose :external_url, documentation: { type: 'string', example: 'https://deploy.gitlab.example.com' }
|
||||
expose :created_at, documentation: { type: 'dateTime', example: '2019-05-25T18:55:13.252Z' }
|
||||
expose :updated_at, documentation: { type: 'dateTime', example: '2019-05-25T18:55:13.252Z' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,13 +6,13 @@ module API
|
|||
class UserList < Grape::Entity
|
||||
include RequestAwareEntity
|
||||
|
||||
expose :id
|
||||
expose :iid
|
||||
expose :project_id
|
||||
expose :created_at
|
||||
expose :updated_at
|
||||
expose :name
|
||||
expose :user_xids
|
||||
expose :id, documentation: { type: 'integer', example: 1 }
|
||||
expose :iid, documentation: { type: 'integer', example: 1 }
|
||||
expose :project_id, documentation: { type: 'integer', example: 2 }
|
||||
expose :created_at, documentation: { type: 'dateTime', example: '2020-02-04T08:13:10.507Z' }
|
||||
expose :updated_at, documentation: { type: 'dateTime', example: '2020-02-04T08:13:10.507Z' }
|
||||
expose :name, documentation: { type: 'string', example: 'user_list' }
|
||||
expose :user_xids, documentation: { type: 'string', example: 'user1,user2' }
|
||||
|
||||
expose :path do |list|
|
||||
project_feature_flags_user_list_path(list.project, list)
|
||||
|
|
|
@ -11,18 +11,27 @@ module API
|
|||
urgency :low
|
||||
|
||||
params do
|
||||
requires :id, type: String, desc: 'The project ID'
|
||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project owned by the authenticated user'
|
||||
end
|
||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||
desc 'Get all environments of the project' do
|
||||
detail 'This feature was introduced in GitLab 8.11.'
|
||||
desc 'List environments' do
|
||||
detail 'Get all environments for a given project. This feature was introduced in GitLab 8.11.'
|
||||
success Entities::Environment
|
||||
is_array true
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
use :pagination
|
||||
optional :name, type: String, desc: 'Returns the environment with this name'
|
||||
optional :search, type: String, desc: 'Returns list of environments matching the search criteria'
|
||||
optional :states, type: String, values: Environment.valid_states.map(&:to_s), desc: 'List all environments that match a specific state'
|
||||
optional :name, type: String, desc: 'Return the environment with this name. Mutually exclusive with search'
|
||||
optional :search, type: String, desc: 'Return list of environments matching the search criteria. Mutually exclusive with name'
|
||||
optional :states,
|
||||
type: String,
|
||||
values: Environment.valid_states.map(&:to_s),
|
||||
desc: 'List all environments that match a specific state. Accepted values: `available`, `stopping`, or `stopped`. If no state value given, returns all environments'
|
||||
mutually_exclusive :name, :search, message: 'cannot be used together'
|
||||
end
|
||||
get ':id/environments' do
|
||||
|
@ -33,15 +42,21 @@ module API
|
|||
present paginate(environments), with: Entities::Environment, current_user: current_user
|
||||
end
|
||||
|
||||
desc 'Creates a new environment' do
|
||||
detail 'This feature was introduced in GitLab 8.11.'
|
||||
desc 'Create a new environment' do
|
||||
detail 'Creates a new environment with the given name and `external_url`. It returns `201` if the environment was successfully created, `400` for wrong parameters. This feature was introduced in GitLab 8.11.'
|
||||
success Entities::Environment
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' },
|
||||
{ code: 422, message: 'Unprocessable entity' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
requires :name, type: String, desc: 'The name of the environment to be created'
|
||||
optional :external_url, type: String, desc: 'URL on which this deployment is viewable'
|
||||
requires :name, type: String, desc: 'The name of the environment'
|
||||
optional :external_url, type: String, desc: 'Place to link to for this environment'
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the new environment. Allowed values are `production`, `staging`, `testing`, `development`, and `other`'
|
||||
end
|
||||
post ':id/environments' do
|
||||
authorize! :create_environment, user_project
|
||||
|
@ -55,17 +70,23 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Updates an existing environment' do
|
||||
detail 'This feature was introduced in GitLab 8.11.'
|
||||
desc 'Update an existing environment' do
|
||||
detail 'Updates an existing environment name and/or `external_url`. It returns `200` if the environment was successfully updated. In case of an error, a status code `400` is returned. This feature was introduced in GitLab 8.11.'
|
||||
success Entities::Environment
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' },
|
||||
{ code: 422, message: 'Unprocessable entity' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
requires :environment_id, type: Integer, desc: 'The environment ID'
|
||||
requires :environment_id, type: Integer, desc: 'The ID of the environment'
|
||||
# TODO: disallow renaming via the API https://gitlab.com/gitlab-org/gitlab/-/issues/338897
|
||||
optional :name, type: String, desc: 'DEPRECATED: Renaming environment can lead to errors, this will be removed in 15.0'
|
||||
optional :external_url, type: String, desc: 'The new URL on which this deployment is viewable'
|
||||
optional :slug, absence: { message: "is automatically generated and cannot be changed" }, documentation: { hidden: true }
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the environment to be created'
|
||||
optional :tier, type: String, values: Environment.tiers.keys, desc: 'The tier of the new environment. Allowed values are `production`, `staging`, `testing`, `development`, and `other`'
|
||||
end
|
||||
put ':id/environments/:environment_id' do
|
||||
authorize! :update_environment, user_project
|
||||
|
@ -80,14 +101,21 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
desc "Delete multiple stopped review apps" do
|
||||
detail "Remove multiple stopped review environments older than a specific age"
|
||||
desc 'Delete multiple stopped review apps' do
|
||||
detail 'It schedules for deletion multiple environments that have already been stopped and are in the review app folder. The actual deletion is performed after 1 week from the time of execution. By default, it only deletes environments 30 days or older. You can change this default using the `before` parameter.'
|
||||
success Entities::EnvironmentBasic
|
||||
failure [
|
||||
{ code: 400, message: 'Bad request' },
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' },
|
||||
{ code: 409, message: 'Conflict' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
optional :before, type: Time, desc: "The timestamp before which environments can be deleted. Defaults to 30 days ago.", default: -> { 30.days.ago }
|
||||
optional :limit, type: Integer, desc: "Maximum number of environments to delete. Defaults to 100.", default: 100, values: 1..1000
|
||||
optional :dry_run, type: Boolean, desc: "If set, perform a dry run where no actual deletions will be performed. Defaults to true.", default: true
|
||||
optional :before, type: Time, desc: "The date before which environments can be deleted. Defaults to 30 days ago. Expected in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`)", default: -> { 30.days.ago }
|
||||
optional :limit, type: Integer, desc: "Maximum number of environments to delete. Defaults to 100", default: 100, values: 1..1000
|
||||
optional :dry_run, type: Boolean, desc: "Defaults to true for safety reasons. It performs a dry run where no actual deletion will be performed. Set to false to actually delete the environment", default: true
|
||||
end
|
||||
delete ":id/environments/review_apps" do
|
||||
authorize! :read_environment, user_project
|
||||
|
@ -107,12 +135,17 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Deletes an existing environment' do
|
||||
detail 'This feature was introduced in GitLab 8.11.'
|
||||
desc 'Delete an environment' do
|
||||
detail 'It returns 204 if the environment was successfully deleted, and 404 if the environment does not exist. This feature was introduced in GitLab 8.11.'
|
||||
success Entities::Environment
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
requires :environment_id, type: Integer, desc: 'The environment ID'
|
||||
requires :environment_id, type: Integer, desc: 'The ID of the environment'
|
||||
end
|
||||
delete ':id/environments/:environment_id' do
|
||||
authorize! :read_environment, user_project
|
||||
|
@ -123,12 +156,18 @@ module API
|
|||
destroy_conditionally!(environment)
|
||||
end
|
||||
|
||||
desc 'Stops an existing environment' do
|
||||
desc 'Stop an environment' do
|
||||
detail 'It returns 200 if the environment was successfully stopped, and 404 if the environment does not exist.'
|
||||
success Entities::Environment
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
requires :environment_id, type: Integer, desc: 'The environment ID'
|
||||
optional :force, type: Boolean, default: false
|
||||
requires :environment_id, type: Integer, desc: 'The ID of the environment'
|
||||
optional :force, type: Boolean, default: false, desc: 'Force environment to stop without executing `on_stop` actions'
|
||||
end
|
||||
post ':id/environments/:environment_id/stop' do
|
||||
authorize! :read_environment, user_project
|
||||
|
@ -141,11 +180,16 @@ module API
|
|||
present environment, with: Entities::Environment, current_user: current_user
|
||||
end
|
||||
|
||||
desc 'Get a single environment' do
|
||||
desc 'Get a specific environment' do
|
||||
success Entities::Environment
|
||||
failure [
|
||||
{ code: 403, message: 'Unauthenticated' },
|
||||
{ code: 404, message: 'Not found' }
|
||||
]
|
||||
tags %w[environments]
|
||||
end
|
||||
params do
|
||||
requires :environment_id, type: Integer, desc: 'The environment ID'
|
||||
requires :environment_id, type: Integer, desc: 'The ID of the environment'
|
||||
end
|
||||
get ':id/environments/:environment_id' do
|
||||
authorize! :read_environment, user_project
|
||||
|
|
|
@ -16,16 +16,19 @@ module API
|
|||
end
|
||||
|
||||
params do
|
||||
requires :id, type: String, desc: 'The ID of a project'
|
||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
||||
end
|
||||
resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||
resource :feature_flags_user_lists do
|
||||
desc 'Get all feature flags user lists of a project' do
|
||||
detail 'This feature was introduced in GitLab 12.10'
|
||||
desc 'List all feature flag user lists for a project' do
|
||||
detail 'Gets all feature flag user lists for the requested project. ' \
|
||||
'This feature was introduced in GitLab 12.10.'
|
||||
success ::API::Entities::FeatureFlag::UserList
|
||||
is_array true
|
||||
tags %w[feature_flags_user_lists]
|
||||
end
|
||||
params do
|
||||
optional :search, type: String, desc: 'Returns the list of user lists matching the search critiera'
|
||||
optional :search, type: String, desc: 'Return user lists matching the search criteria'
|
||||
|
||||
use :pagination
|
||||
end
|
||||
|
@ -35,9 +38,10 @@ module API
|
|||
with: ::API::Entities::FeatureFlag::UserList
|
||||
end
|
||||
|
||||
desc 'Create a feature flags user list for a project' do
|
||||
detail 'This feature was introduced in GitLab 12.10'
|
||||
desc 'Create a feature flag user list' do
|
||||
detail 'Creates a feature flag user list. This feature was introduced in GitLab 12.10.'
|
||||
success ::API::Entities::FeatureFlag::UserList
|
||||
tags %w[feature_flags_user_lists]
|
||||
end
|
||||
params do
|
||||
requires :name, type: String, desc: 'The name of the list'
|
||||
|
@ -59,12 +63,13 @@ module API
|
|||
end
|
||||
|
||||
params do
|
||||
requires :iid, type: String, desc: 'The internal ID of the user list'
|
||||
requires :iid, types: [String, Integer], desc: "The internal ID of the project's feature flag user list"
|
||||
end
|
||||
resource 'feature_flags_user_lists/:iid' do
|
||||
desc 'Get a single feature flag user list belonging to a project' do
|
||||
detail 'This feature was introduced in GitLab 12.10'
|
||||
desc 'Get a feature flag user list' do
|
||||
detail 'Gets a feature flag user list. This feature was introduced in GitLab 12.10.'
|
||||
success ::API::Entities::FeatureFlag::UserList
|
||||
tags %w[feature_flags_user_lists]
|
||||
end
|
||||
get do
|
||||
present user_project.operations_feature_flags_user_lists.find_by_iid!(params[:iid]),
|
||||
|
@ -72,8 +77,9 @@ module API
|
|||
end
|
||||
|
||||
desc 'Update a feature flag user list' do
|
||||
detail 'This feature was introduced in GitLab 12.10'
|
||||
detail 'Updates a feature flag user list. This feature was introduced in GitLab 12.10.'
|
||||
success ::API::Entities::FeatureFlag::UserList
|
||||
tags %w[feature_flags_user_lists]
|
||||
end
|
||||
params do
|
||||
optional :name, type: String, desc: 'The name of the list'
|
||||
|
@ -93,8 +99,9 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Delete a feature flag user list' do
|
||||
detail 'This feature was introduced in GitLab 12.10'
|
||||
desc 'Delete feature flag user list' do
|
||||
detail 'Deletes a feature flag user list. This feature was introduced in GitLab 12.10.'
|
||||
tags %w[feature_flags_user_lists]
|
||||
end
|
||||
delete do
|
||||
# TODO: Move the business logic to a service class in app/services/feature_flags.
|
||||
|
|
|
@ -86,7 +86,11 @@ module Gitlab
|
|||
analyzers.each do |analyzer|
|
||||
next if analyzer.suppressed? && !analyzer.requires_tracking?(parsed)
|
||||
|
||||
analyzer.analyze(parsed)
|
||||
if analyzer.raw?
|
||||
analyzer.analyze(sql)
|
||||
else
|
||||
analyzer.analyze(parsed)
|
||||
end
|
||||
rescue StandardError, ::Gitlab::Database::QueryAnalyzers::Base::QueryAnalyzerError => e
|
||||
# We catch all standard errors to prevent validation errors to introduce fatal errors in production
|
||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
|
||||
|
|
|
@ -53,6 +53,10 @@ module Gitlab
|
|||
Thread.current[self.context_key]
|
||||
end
|
||||
|
||||
def self.raw?
|
||||
false
|
||||
end
|
||||
|
||||
def self.enabled?
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
|
45
lib/gitlab/database/query_analyzers/query_recorder.rb
Normal file
45
lib/gitlab/database/query_analyzers/query_recorder.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Database
|
||||
module QueryAnalyzers
|
||||
class QueryRecorder < Base
|
||||
LOG_FILE = 'rspec/query_recorder.ndjson'
|
||||
|
||||
class << self
|
||||
def raw?
|
||||
true
|
||||
end
|
||||
|
||||
def enabled?
|
||||
# Only enable QueryRecorder in CI
|
||||
ENV['CI'].present?
|
||||
end
|
||||
|
||||
def analyze(sql)
|
||||
payload = {
|
||||
sql: sql
|
||||
}
|
||||
|
||||
log_query(payload)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_query(payload)
|
||||
log_path = Rails.root.join(LOG_FILE)
|
||||
log_dir = File.dirname(log_path)
|
||||
|
||||
# Create log directory if it does not exist since it is only created
|
||||
# ahead of time by certain CI jobs
|
||||
FileUtils.mkdir_p(log_dir) unless Dir.exist?(log_dir)
|
||||
|
||||
log_line = "#{Gitlab::Json.dump(payload)}\n"
|
||||
|
||||
File.write(log_path, log_line, mode: 'a')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4548,9 +4548,6 @@ msgstr ""
|
|||
msgid "Analytics"
|
||||
msgstr ""
|
||||
|
||||
msgid "AnalyticsDashboards|Dashboards"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analyze your dependencies for known vulnerabilities."
|
||||
msgstr ""
|
||||
|
||||
|
@ -25468,6 +25465,9 @@ msgstr ""
|
|||
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
|
||||
msgstr ""
|
||||
|
||||
msgid "Merge requests can't be merged if the status checks did not succeed or are still running."
|
||||
msgstr ""
|
||||
|
||||
msgid "Merge the feature branch into the target branch and fix any conflicts. %{linkStart}How do I fix them?%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -32060,6 +32060,9 @@ msgstr ""
|
|||
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectSettings|Status checks must succeed"
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectSettings|Submit changes to be merged upstream."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { GlFormGroup, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { placeholderForType } from 'jh_else_ce/integrations/constants';
|
||||
|
||||
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
|
||||
|
||||
|
@ -28,6 +29,50 @@ describe('TriggerFields', () => {
|
|||
const findAllGlFormCheckboxes = () => wrapper.findAllComponents(GlFormCheckbox);
|
||||
const findAllGlFormInputs = () => wrapper.findAllComponents(GlFormInput);
|
||||
|
||||
describe('placeholder text on the event fields and default values', () => {
|
||||
const dummyFieldPlaceholder = '#foo';
|
||||
const integrationTypes = {
|
||||
INTEGRATION_TYPE_SLACK: 'slack',
|
||||
INTEGRATION_TYPE_SLACK_APPLICATION: 'gitlab_slack_application',
|
||||
INTEGRATION_TYPE_MATTERMOST: 'mattermost',
|
||||
INTEGRATION_TYPE_NON_EXISTING: 'non_existing',
|
||||
};
|
||||
it.each`
|
||||
integrationType | fieldPlaceholder | expectedPlaceholder
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK} | ${undefined} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_SLACK]}
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK} | ${''} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_SLACK]}
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK} | ${dummyFieldPlaceholder} | ${dummyFieldPlaceholder}
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK_APPLICATION} | ${undefined} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_SLACK_APPLICATION]}
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK_APPLICATION} | ${''} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_SLACK_APPLICATION]}
|
||||
${integrationTypes.INTEGRATION_TYPE_SLACK_APPLICATION} | ${dummyFieldPlaceholder} | ${dummyFieldPlaceholder}
|
||||
${integrationTypes.INTEGRATION_TYPE_MATTERMOST} | ${undefined} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_MATTERMOST]}
|
||||
${integrationTypes.INTEGRATION_TYPE_MATTERMOST} | ${''} | ${placeholderForType[integrationTypes.INTEGRATION_TYPE_MATTERMOST]}
|
||||
${integrationTypes.INTEGRATION_TYPE_MATTERMOST} | ${dummyFieldPlaceholder} | ${dummyFieldPlaceholder}
|
||||
${integrationTypes.INTEGRATION_TYPE_NON_EXISTING} | ${undefined} | ${undefined}
|
||||
${integrationTypes.INTEGRATION_TYPE_NON_EXISTING} | ${''} | ${undefined}
|
||||
${integrationTypes.INTEGRATION_TYPE_NON_EXISTING} | ${dummyFieldPlaceholder} | ${dummyFieldPlaceholder}
|
||||
`(
|
||||
'passed down correct placeholder for "$integrationType" type and "$fieldPlaceholder" placeholder on the field',
|
||||
({ integrationType, fieldPlaceholder, expectedPlaceholder }) => {
|
||||
createComponent({
|
||||
type: integrationType,
|
||||
events: [
|
||||
{
|
||||
field: {
|
||||
name: 'foo',
|
||||
value: '',
|
||||
placeholder: fieldPlaceholder,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const field = wrapper.findComponent(GlFormInput);
|
||||
|
||||
expect(field.attributes('placeholder')).toBe(expectedPlaceholder);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe.each([true, false])('template, isInheriting = `%p`', (isInheriting) => {
|
||||
it('renders a label with text "Trigger"', () => {
|
||||
createComponent();
|
||||
|
|
|
@ -10,6 +10,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
|
|||
before do
|
||||
allow(described_class.instance).to receive(:all_analyzers).and_return([analyzer, disabled_analyzer])
|
||||
allow(analyzer).to receive(:enabled?).and_return(true)
|
||||
allow(analyzer).to receive(:raw?).and_return(false)
|
||||
allow(analyzer).to receive(:suppressed?).and_return(false)
|
||||
allow(analyzer).to receive(:begin!)
|
||||
allow(analyzer).to receive(:end!)
|
||||
|
@ -181,6 +182,13 @@ RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
|
|||
expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'does call analyze with raw sql when raw? is true' do
|
||||
expect(analyzer).to receive(:raw?).and_return(true)
|
||||
expect(analyzer).to receive(:analyze).with('SELECT 1 FROM projects')
|
||||
|
||||
expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
|
||||
end
|
||||
|
||||
def process_sql(sql)
|
||||
described_class.instance.within do
|
||||
ApplicationRecord.load_balancer.read_write do |connection|
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Database::QueryAnalyzers::QueryRecorder, query_analyzers: false do
|
||||
# We keep only the QueryRecorder analyzer running
|
||||
around do |example|
|
||||
described_class.with_suppressed(false) do
|
||||
example.run
|
||||
end
|
||||
end
|
||||
|
||||
context 'when analyzer is enabled for tests' do
|
||||
let(:query) { 'SELECT 1 FROM projects' }
|
||||
let(:log_path) { Rails.root.join(described_class::LOG_FILE) }
|
||||
|
||||
before do
|
||||
stub_env('CI', 'true')
|
||||
|
||||
# This is needed to be able to stub_env the CI variable
|
||||
::Gitlab::Database::QueryAnalyzer.instance.begin!([described_class])
|
||||
end
|
||||
|
||||
after do
|
||||
::Gitlab::Database::QueryAnalyzer.instance.end!([described_class])
|
||||
end
|
||||
|
||||
it 'logs queries to a file' do
|
||||
allow(FileUtils).to receive(:mkdir_p)
|
||||
.with(File.dirname(log_path))
|
||||
expect(File).to receive(:write)
|
||||
.with(log_path, /^{"sql":"#{query}/, mode: 'a')
|
||||
expect(described_class).to receive(:analyze).with(/^#{query}/).and_call_original
|
||||
|
||||
expect { ApplicationRecord.connection.execute(query) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
9
spec/support/database/query_recorder.rb
Normal file
9
spec/support/database/query_recorder.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.configure do |config|
|
||||
# Truncate the query_recorder log file before starting the suite
|
||||
config.before(:suite) do
|
||||
log_path = Rails.root.join(Gitlab::Database::QueryAnalyzers::QueryRecorder::LOG_FILE)
|
||||
File.write(log_path, '') if File.exist?(log_path)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue