diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-07 15:08:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-07 15:08:06 +0300 |
commit | 6c42aa7c56f2909f2a4f1f178197cfa7d927ce8d (patch) | |
tree | e1ed35cc48611196253134862e6af92bc7fa6844 | |
parent | aeb70fd397271bef3857095468172e46a2965bc1 (diff) |
Add latest changes from gitlab-org/gitlab@master
34 files changed, 373 insertions, 279 deletions
diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md index 7e622dbe62c..c1321dd9f96 100644 --- a/.gitlab/merge_request_templates/Deprecations.md +++ b/.gitlab/merge_request_templates/Deprecations.md @@ -27,9 +27,9 @@ Deprecation announcements can and should be created and merged into Docs at any Please review: -- The definitions of ["Deprecation", "End of Support", and "Removal"](https://docs.gitlab.com/ee/development/deprecation_guidelines/#terminology). -- The [guidelines for deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations). -- The process for [creating a deprecation entry](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry). +- The definitions of ["Deprecation", "End of Support", and "Removal"](https://docs.gitlab.com/ee/development/deprecation_guidelines/). +- The [guidelines for deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations-removals-and-breaking-changes). +- The process for [creating a deprecation announcement](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-the-announcement). They are frequently updated, and everyone should make sure they are aware of the current standards (PM, PMM, EM, and TW). @@ -38,7 +38,7 @@ They are frequently updated, and everyone should make sure they are aware of the - [ ] Set yourself as the Assignee, meaning you are the DRI. - [ ] If the deprecation is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`. - [ ] Confirm this MR is labeled ~"release post item::deprecation" -- [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry). +- [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-the-announcement). - [ ] Add reviewers by the 10th. - [ ] Add scoped `devops::` and `group::` labels as necessary. - [ ] Add the appropriate milestone to this MR. @@ -48,8 +48,8 @@ They are frequently updated, and everyone should make sure they are aware of the When the content is ready for review, it must be reviewed by a Technical Writer and Engineering Manager, but can also be reviewed by Product Marketing, Product Design, and the Product Leaders for this area. Please use the -[reviewers](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/) -feature for all reviews. Reviewers will then `approve` the MR and remove themselves from Reviewers when their review is complete. +[reviewers](https://docs.gitlab.com/ee/development/code_review.html#dogfooding-the-reviewers-feature) +feature for all reviews. Reviewers will then approve the MR and remove themselves from Reviewers when their review is complete. - [ ] (Recommended) PMM - [ ] (Optional) Product Designer @@ -81,7 +81,7 @@ yourself as a reviewer if it's not ready for merge yet. - All links must be full URLs, as the deprecation YAML files are used in two different projects. Do not use relative links. The generated doc is an exception to the relative link rule and currently uses absolute links only. - Make sure all links and anchors are correct. Do not link to the H1 (top) anchor on a docs page. - [ ] Code. Make sure any included code is wrapped in code blocks. -- [ ] Capitalization. Make sure to capitalize feature names. Stay consistent with the Documentation Style Guidance on [Capitalization](https://docs.gitlab.com/ee/development/documentation/styleguide.html#capitalization). +- [ ] Capitalization. Make sure to capitalize feature names. Stay consistent with the Documentation Style Guidance on [Capitalization](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#capitalization). - [ ] Blank spaces. Remove unnecessary spaces (end of line spaces, double spaces, extra blank lines, and lines with only spaces). </details> diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index cfecc4756b9..be750a04f7c 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -1895,7 +1895,6 @@ Layout/ArgumentAlignment: - 'spec/requests/recursive_webhook_detection_spec.rb' - 'spec/requests/users/group_callouts_spec.rb' - 'spec/requests/users/project_callouts_spec.rb' - - 'spec/requests/verifies_with_email_spec.rb' - 'spec/routing/environments_spec.rb' - 'spec/routing/group_routing_spec.rb' - 'spec/routing/project_routing_spec.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 689219fe59f..6bc06509d4b 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -731a667ba261319e7c2d32229b5bbbe3e7cc34b7 +e8a0d0187f11908018a4f639d0b845501153eddb diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item.vue b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item.vue index d0f206e767f..460f508ee74 100644 --- a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item.vue +++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item.vue @@ -54,6 +54,13 @@ export default { `${this.startInNumber} ${this.startInUnit}${plural}`, ); }, + updateWhen(when) { + this.$emit('update-job', 'rules[0].when', when); + + if (when === JOB_RULES_WHEN.delayed.value) { + this.updateStartIn(); + } + }, }, }; </script> @@ -73,7 +80,7 @@ export default { :options="$options.whenOptions" data-testid="rules-when-select" :value="job.rules[0].when" - @input="$emit('update-job', 'rules[0].when', $event)" + @input="updateWhen" /> </gl-form-group> <gl-form-group diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue index 4571c4172e5..c854d865869 100644 --- a/app/assets/javascripts/members/components/table/role_dropdown.vue +++ b/app/assets/javascripts/members/components/table/role_dropdown.vue @@ -76,6 +76,7 @@ export default { newRoleName, ); if (!confirmed) { + this.selectedRoleValue = currentRoleValue; this.busy = false; return; } diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue index baf2ce2aa9c..ae28694f5d2 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue @@ -8,7 +8,7 @@ import ServiceDeskSetting from './service_desk_setting.vue'; export default { serviceDeskEmailHelpPath: helpPagePath('/user/project/service_desk.html', { - anchor: 'use-a-custom-email-address', + anchor: 'use-an-additional-service-desk-alias-email', }), components: { GlAlert, diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue index 36a49625116..5078cbbdf59 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue @@ -111,12 +111,12 @@ export default { }, emailSuffixHelpUrl() { return helpPagePath('user/project/service_desk.html', { - anchor: 'configure-a-custom-email-address-suffix', + anchor: 'configure-a-suffix-for-service-desk-alias-email', }); }, serviceDeskEmailAddressHelpUrl() { return helpPagePath('user/project/service_desk.html', { - anchor: 'use-a-custom-email-address', + anchor: 'use-an-additional-service-desk-alias-email', }); }, issuesHelpPagePath() { diff --git a/app/controllers/concerns/verifies_with_email.rb b/app/controllers/concerns/verifies_with_email.rb index 45869c05f41..13378800ea9 100644 --- a/app/controllers/concerns/verifies_with_email.rb +++ b/app/controllers/concerns/verifies_with_email.rb @@ -25,6 +25,7 @@ module VerifiesWithEmail if user.valid_password?(user_params[:password]) # The user has logged in successfully. + if user.unlock_token # Prompt for the token if it already has been set prompt_for_email_verification(user) @@ -32,7 +33,8 @@ module VerifiesWithEmail # require email verification if: # - their account has been locked because of too many failed login attempts, or # - they have logged in before, but never from the current ip address - send_verification_instructions(user) + reason = 'sign in from untrusted IP address' unless user.access_locked? + send_verification_instructions(user, reason: reason) prompt_for_email_verification(user) end end @@ -75,13 +77,13 @@ module VerifiesWithEmail super end - def send_verification_instructions(user) + def send_verification_instructions(user, reason: nil) return if send_rate_limited?(user) service = Users::EmailVerification::GenerateTokenService.new(attr: :unlock_token, user: user) raw_token, encrypted_token = service.execute user.unlock_token = encrypted_token - user.lock_access!({ send_instructions: false }) + user.lock_access!({ send_instructions: false, reason: reason }) send_verification_instructions_email(user, raw_token) end diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index f6a6648fd79..5c0c2b4adf2 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -277,9 +277,6 @@ class GraphqlController < ApplicationController def execute_introspection_query if introspection_query_can_use_cache? - Gitlab::AppLogger.info(message: "IntrospectionQueryCache hit") - log_introspection_query_cache_details(true) - # Context for caching: https://gitlab.com/gitlab-org/gitlab/-/issues/409448 Rails.cache.fetch( introspection_query_cache_key, @@ -287,9 +284,6 @@ class GraphqlController < ApplicationController execute_query.to_json end else - Gitlab::AppLogger.info(message: "IntrospectionQueryCache miss") - log_introspection_query_cache_details(false) - execute_query end end @@ -314,16 +308,6 @@ class GraphqlController < ApplicationController end end - def log_introspection_query_cache_details(can_use_introspection_query_cache) - Gitlab::AppLogger.info( - message: "IntrospectionQueryCache", - can_use_introspection_query_cache: can_use_introspection_query_cache.to_s, - query: query, - variables: build_variables(params[:variables]).to_s, - introspection_query_cache_key: introspection_query_cache_key.to_s - ) - end - def graphql_query_object @graphql_query_object ||= GraphQL::Query.new(GitlabSchema, query: query, variables: build_variables(params[:variables])) diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb index 89e8a261288..281ac14d3ce 100644 --- a/app/controllers/projects/alerting/notifications_controller.rb +++ b/app/controllers/projects/alerting/notifications_controller.rb @@ -72,7 +72,7 @@ module Projects end def endpoint_identifier - params[:endpoint_identifier] || AlertManagement::HttpIntegration::LEGACY_IDENTIFIER + params[:endpoint_identifier] || AlertManagement::HttpIntegration::LEGACY_IDENTIFIERS end def notification_payload diff --git a/app/models/alert_management/http_integration.rb b/app/models/alert_management/http_integration.rb index d5162865a79..bf4738272de 100644 --- a/app/models/alert_management/http_integration.rb +++ b/app/models/alert_management/http_integration.rb @@ -4,7 +4,7 @@ module AlertManagement class HttpIntegration < ApplicationRecord include ::Gitlab::Routing - LEGACY_IDENTIFIER = 'legacy' + LEGACY_IDENTIFIERS = %w[legacy legacy-prometheus].freeze belongs_to :project, inverse_of: :alert_management_http_integrations @@ -20,7 +20,7 @@ module AlertManagement validates :token, presence: true, format: { with: /\A\h{32}\z/ } validates :name, presence: true, length: { maximum: 255 } validates :type_identifier, presence: true - validates :endpoint_identifier, presence: true, length: { maximum: 255 }, format: { with: /\A[A-Za-z0-9]+\z/ } + validates :endpoint_identifier, presence: true, length: { maximum: 255 }, format: { with: /\A[A-Za-z0-9-]+\z/ } validates :endpoint_identifier, uniqueness: { scope: [:project_id, :active] }, if: :active? validates :payload_attribute_mapping, json_schema: { filename: 'http_integration_payload_attribute_mapping' } @@ -33,7 +33,6 @@ module AlertManagement scope :for_type, ->(type) { where(type_identifier: type) } scope :for_project, ->(project_ids) { where(project: project_ids) } scope :active, -> { where(active: true) } - scope :legacy, -> { for_endpoint_identifier(LEGACY_IDENTIFIER) } scope :ordered_by_type_and_id, -> { order(:type_identifier, :id) } enum type_identifier: { @@ -42,16 +41,18 @@ module AlertManagement } def url - if legacy? - return project_alerts_notify_url(project, format: :json) if http? - return notify_project_prometheus_alerts_url(project, format: :json) if prometheus? + case endpoint_identifier + when 'legacy' + project_alerts_notify_url(project, format: :json) + when 'legacy-prometheus' + notify_project_prometheus_alerts_url(project, format: :json) + else + project_alert_http_integration_url(project, name_slug, endpoint_identifier, format: :json) end - - project_alert_http_integration_url(project, name_slug, endpoint_identifier, format: :json) end def legacy? - endpoint_identifier == LEGACY_IDENTIFIER + LEGACY_IDENTIFIERS.include?(endpoint_identifier) end private diff --git a/app/models/user.rb b/app/models/user.rb index adbbdf9b0ae..7fd5d25d7e0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2063,7 +2063,7 @@ class User < ApplicationRecord # override, from Devise def lock_access!(opts = {}) Gitlab::AppLogger.info("Account Locked: username=#{username}") - audit_lock_access + audit_lock_access(reason: opts.delete(:reason)) super end @@ -2599,7 +2599,7 @@ class User < ApplicationRecord end # method overriden in EE - def audit_lock_access; end + def audit_lock_access(reason: nil); end # method overriden in EE def audit_unlock_access(author: self); end diff --git a/app/services/clusters/agent_tokens/create_service.rb b/app/services/clusters/agent_tokens/create_service.rb index efa9716d2c8..136afd108e7 100644 --- a/app/services/clusters/agent_tokens/create_service.rb +++ b/app/services/clusters/agent_tokens/create_service.rb @@ -40,8 +40,6 @@ module Clusters end def active_tokens_limit_reached? - return false unless Feature.enabled?(:cluster_agents_limit_tokens_created) - ::Clusters::AgentTokensFinder.new(agent, current_user, status: :active).execute.count >= ACTIVE_TOKENS_LIMIT end diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb index f1c093c89b7..22a882c4648 100644 --- a/app/services/projects/prometheus/alerts/notify_service.rb +++ b/app/services/projects/prometheus/alerts/notify_service.rb @@ -89,7 +89,9 @@ module Projects # AlertManagement::HttpIntegrations is complete, # we should use use the HttpIntegration as SSOT. # Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/409734 - return false if project.alert_management_http_integrations.legacy.prometheus.any? + return false if project.alert_management_http_integrations + .for_endpoint_identifier('legacy-prometheus') + .any? prometheus = project.find_or_initialize_integration('prometheus') return false unless prometheus.manual_configuration? diff --git a/config/feature_flags/development/cluster_agents_limit_tokens_created.yml b/config/feature_flags/development/cluster_agents_limit_tokens_created.yml deleted file mode 100644 index 77a4bae6a56..00000000000 --- a/config/feature_flags/development/cluster_agents_limit_tokens_created.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: cluster_agents_limit_tokens_created -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120825 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412399 -milestone: '16.1' -type: development -group: group::environments -default_enabled: true diff --git a/config/feature_flags/development/p_ci_builds_metadata_foreign_key.yml b/config/feature_flags/development/p_ci_builds_metadata_foreign_key.yml deleted file mode 100644 index 9d6c6e9612e..00000000000 --- a/config/feature_flags/development/p_ci_builds_metadata_foreign_key.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: p_ci_builds_metadata_foreign_key -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124865 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414396 -milestone: '16.2' -type: development -group: group::pipeline execution -default_enabled: false diff --git a/doc/architecture/blueprints/runner_admission_controller/index.md b/doc/architecture/blueprints/runner_admission_controller/index.md new file mode 100644 index 00000000000..420232895d1 --- /dev/null +++ b/doc/architecture/blueprints/runner_admission_controller/index.md @@ -0,0 +1,241 @@ +--- +status: proposed +creation-date: "2023-03-07" +authors: [ "@username" ] +coach: "@username" +approvers: [ "@product-manager", "@engineering-manager" ] +owning-stage: "~devops::<stage>" +participating-stages: [] +--- + +# GitLab Runner Admissions Controller + +The GitLab `admission controller` (inspired by the [Kubernetes admission controller concept](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/)) is a proposed technical solution to intercept jobs before they're persisted or added to the build queue for execution. + +An admission controller can be registered to the GitLab instance and receive a payload containing jobs to be created. Admission controllers can be _mutating_, _validating_, or both. + +- When _mutating_, mutatable job information can be modified and sent back to the GitLab instance. Jobs can be modified to conform to organizational policy, security requirements, or have, for example, their tag list modified so that they're routed to specific runners. +- When _validating_, a job can be denied execution. + +## Motivation + +To comply with the segregation of duties, organizational policy, or security requirements, customers in financial services, the US federal government market segment, or other highly regulated industries must ensure that only authorized users can use runners associated with particular CI job environments. + +In this context, using the term environments is not equivalent to the definition of the environment used in the GitLab CI environments and deployments documentation. Using the definition from the [SLSA guide](https://slsa.dev/spec/v0.1/terminology), an environment is the "machine, container, VM, or similar in which the job runs.” + +An additional requirement comes from the Remote Computing Enablement (RCE) group at [Lawrence Livermore National Laboratory](https://hpc.llnl.gov/). In this example, users must have a user ID on the target Runner CI build environment for the CI job to run. To simplify administration across the entire user base, RCE needs to be able to associate a Runner with a GitLab user entity. + +### Current GitLab CI job handling mechanism + +Before going further, it is helpful to level-set the current job handling mechanism in GitLab CI and GitLab Runners. + +- First, a runner associated with a GitLab instance continuously queries the GitLab instance API to check if there is a new job that it could run. +- With every push to a project repository on GitLab with a `.gitlab-ci.yml` file present, the CI service present on the GitLab instance catches the event and triggers a new CI job. +- The CI job enters a pending state in the queue until a Runner requests a job from the instance. +- On the request from a runner to the API for a job, the database is queried to verify that the job parameters matches that of the runner. In other words, when runners poll a GitLab instance for a job to execute they're assigned a job if it matches the specified criteria. +- If the job matches the runner in question, then the GitLab instance connects the job to the runner and changes the job state to running. In other words, GitLab connects the `job` object with the `Runner` object. +- A runner can be configured to run un-tagged jobs. Tags are the primary mechanism used today to enable customers to have some control of which Runners run certain types of jobs. +- So while runners are scoped to the instance, group, or project, there are no additional access control mechanisms today that can easily be expanded on to deny access to a runner based on a user or group identifier. + +The current CI jobs queue logic is as follows. **Note - in the code ww still use the very old `build` naming construct, but we've migrated from `build` to `job` in the product and documentation. + +```ruby +jobs = + if runner.instance_type? + jobs_for_shared_runner + elsif runner.group_type? + jobs_for_group_runner + else + jobs_for_project_runner + end + +# select only jobs that have tags known to the runner +jobs = jobs.matches_tag_ids(runner.tags.ids) + +# select builds that have at least one tag if required +unless runner.run_untagged? + jobs = jobs.with_any_tags +end + +``` + +## Goals + +- Implement an initial solution that provides an easy-to-configure and use mechanism to `allow`, `deny` or `redirect` CI job execution on a specific runner entity based on some basic job details (like user, group or project membership). + +## Non-Goals + +- A re-design of the CI job queueing mechanism is not in the scope of this blueprint. + +## Proposal + +Implement a mechanism, `admission controllers`, to intercept CI jobs, allowing them to either mutate jobs, validate them or do both. An admission controller is a mutating webhook that can modify the CI job or reject the job according to a policy. The webhook is called before the job is inserted into the CI jobs queue. + +### Guiding principles + +- The webhook payload schema will be part of our public facing APIs. +- We must maintain backwards compatibility when extending the webhook payload. +- Controllers should be idempotent. + +### How will the admissions controller work? + +**Scenario 1**: I want to deny access to a certain runner. + +1. Configure an admissions controller to only accept jobs from specific projects. +1. When a job is created the `project information` (`project_id`, `job_id`, `api_token`) will be used to query GitLab for specific details. +1. If the `project information` matches the allow list, then the job payload is not modified and the job is able to run on the target runner. +1. If the `project information` does not match the allow list, then the job payload is not modified and the job is dropped. +1. The job tags are not changed. +1. Admission controller may optionally send back an arbitrary text description of why a decline decision was made. + +**Scenario 2**: Large runner fleet with using a common configuration and tags. + +Each runner has a tag such as `zone_a`, `zone_b`. In this scenario the customer does not know where a specific job can run as some users have access to `zone_a`, and some to `zone_b`. The customer does not want to fail a job that should run on `zone_a`, but instead redirect a job if it is not correctly tagged to run in `zone_a.` + +1. Configure an admissions controller to mutate jobs based on `user_id`. +1. When a job is created the `project information` (`project_id`, `job_id`, `api_token`) will be used to query GitLab for specific details. +1. If the `user_id` matches then the admissions controller modifies the job tag list. `zone_a` is added to the tag list as the controller has detected that the user triggering the job should have their jobs run IN `zone_a`. + +### MVC + +#### Admission controller + +1. A single admission controller can be registered at the instance level only. +1. The admission controller must respond within 30 seconds. +1. The admission controller will receive an array of individual jobs. These jobs may or may not be related to each other. The response must contain only responses to the jobs made as part of the request. + +#### Job Lifecycle + +1. The lifecycle of a job will be updated to include a new `validating` state. + + ```mermaid + stateDiagram-v2 + created --> validating + state validating { + [*] --> accept + [*] --> reject + } + reject --> failed + accept --> pending + pending --> running: picked by runner + running --> executed + state executed { + [*] --> failed + [*] --> success + [*] --> canceled + } + executed --> created: retry + ``` + +1. When the state is `validating`, the mutating webhook payload is sent to the admission controller. +1. For jobs where the webhook times out (30 seconds) their status should be set as though the admission was denied. This should +be rare in typical circumstances. +1. Jobs with denied admission can be retried. Retried jobs will be resent to the admission controller along with any mutations that they received previously. +1. [`allow_failure`](../../../ci/yaml/index.md#allow_failure) should be updated to support jobs that fail on denied admissions, for example: + + ```yaml + job: + script: + - echo "I will fail admission" + allow_failure: + on_denied_admission: true + ``` + +1. The UI should be updated to display the reason for any job mutations (if provided). +1. A table in the database should be created to store the mutations. Any changes that were made, like tags, should be persisted and attached to `ci_builds` with `acts_as_taggable :admission_tags`. + +#### Payload + +1. The payload is comprised of individual job entries consisting of: + - Job ID. + - [Predefined variables](../../../ci/variables/predefined_variables.md) + - Job tag list. +1. The response payload is comprised of individual job entries consisting of: + - Job ID. + - Admission state: `accepted` or `denied`. + - Mutations: Only `tags` is supported for now. The tags provided replaces the original tag list. + - Reason: A controller can provide a reason for admission and mutation. + +##### Example request + +```json +[ + { + "id": 123, + "variables": { + # predefined variables: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html + "CI_PROJECT_ID": 123, + "CI_PROJECT_NAME": "something", + "GITLAB_USER_ID": 98123, + ... + }, + "tags": [ "docker", "windows" ] + }, + { + "id": 245, + "variables": { + "CI_PROJECT_ID": 245, + "CI_PROJECT_NAME": "foobar", + "GITLAB_USER_ID": 98123, + ... + }, + "tags": [ "linux", "eu-west" ] + }, + { + "id": 666, + "variables": { + "CI_PROJECT_ID": 666, + "CI_PROJECT_NAME": "do-bad-things", + "GITLAB_USER_ID": 98123, + ... + }, + "tags": [ "secure-runner" ] + }, +] +``` + +##### Example response + +```json +[ + { + "id": 123, + "admission": "accepted", + "reason": "it's always-allow-day-wednesday" + }, + { + "id": 245, + "admission": "accepted", + "mutations": { + "tags": [ "linux", "us-west" ] + }, + "reason": "user is US employee: retagged region" + }, + { + "id": 666, + "admission": "rejected", + "reason": "you have no power here" + }, +] +``` + +### MVC + + +1. Multiple admissions controllers on groups and project levels. +1. Passing job definition through a chain of the controllers (starting on the project, through all defined group controllers up to the instance controller). +1. Each level gets the definition modified by the previous controller in the chain and makes decisions based on the current state. +1. Modification reasons, if reported by multiple controllers, are concatenated. +1. Usage of the admission controller is optional, so we can have a chain containing project+instance, project+group+parent group+instance, project+group, group+instance, etc + +### Implementation Details + +1. [placeholder for steps required to code the admissions controller MVC] + +## Technical issues to resolve + +| issue | resolution| +| ------ | ------ | +|We may have conflicting tag-sets as mutating controller can make it possible to define AND, OR and NONE logical definition of tags. This can get quite complex quickly. | | +|Rule definition for the queue web hook| +|What data to send to the admissions controller? Is it a subset or all of the [predefined variables](../../../ci/variables/predefined_variables.md)?| +|Is the `queueing web hook` able to run at GitLab.com scale? On GitLab.com we would trigger millions of webhooks per second and the concern is that would overload Sidekiq or be used to abuse the system. diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md deleted file mode 100644 index c2630d6810d..00000000000 --- a/doc/ci/pipelines/job_artifacts.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -redirect_to: '../jobs/job_artifacts.md' -remove_date: '2023-07-04' ---- - -This document was moved to [another location](../jobs/job_artifacts.md). - -<!-- This redirect file can be deleted after <2023-07-04>. --> -<!-- Redirects that point to other docs in the same project expire in three months. --> -<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. --> -<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index 459c23bc0ea..95c843ebf34 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -1551,11 +1551,20 @@ When names change, it is more complicated to search or grep text that has line b Tier badges are displayed as orange text next to a topic title. These badges link to the GitLab pricing page. -You must assign a tier badge: +You should assign a tier badge: - To all H1 topic titles, except the pages under `doc/development/*`. - To topic titles that don't apply to the same tier as the H1. +The H1 tier badge should be the badge that applies to the lowest tier for the features on the page. + +Some pages won't have a tier badge, because no obvious tier badge applies. For example: + +- Tutorials. +- Pages that compare features from different tiers. + +#### Add a tier badge + To add a tier badge to a topic title, add the relevant tier badge after the title text. For example: diff --git a/doc/subscriptions/customers_portal.md b/doc/subscriptions/customers_portal.md index 07e6e952419..3a807c5dfd3 100644 --- a/doc/subscriptions/customers_portal.md +++ b/doc/subscriptions/customers_portal.md @@ -13,15 +13,32 @@ If you made your purchase through an authorized reseller, you must contact them You can also specifically manage your [GitLab SaaS subscription](gitlab_com/index.md) or [self-managed subscription](self_managed/index.md). -## Change account owner information +## Sign in to Customers Portal + +You can sign in to Customers Portal either with your GitLab.com account or your email and password (if you have not yet [linked your Customers Portal account to your GitLab.com account](#link-a-gitlabcom-account)). + +NOTE: +If you registered for Customers Portal with your GitLab.com account, sign in with this account. + +To sign in to Customers Portal using your GitLab.com account: -Account owner personal details are used on invoices. The account owner email address is used for the Customers Portal legacy login and license-related email. +1. Navigate to [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Select **Continue with your GitLab.com account**. + +To sign in to Customers Portal using your email and password: + +1. Navigate to [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Select **Sign in with your email and password**. +1. Provide the **Email** and **Password** for your Customers Portal account. +1. Select **Sign in**. + +## Change account owner information -If you have registered a Customers Portal account through a GitLab.com account, the GitLab.com account is used for login. +The account owner's personal details are used on invoices. The account owner's email address is used for the [Customers Portal legacy sign-in](#sign-in-to-customers-portal) and license-related email. To change account owner information, including name, billing address, and email address: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. Select **My account > Account details**. 1. Expand the **Personal details** section. 1. Edit the personal details. @@ -37,7 +54,7 @@ to another person, after you enter that person's personal details, you must also To change your company details, including company name and VAT number: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. Select **My account > Account details**. 1. Expand the **Company details** section. 1. Edit the company details. @@ -54,7 +71,7 @@ If you would like to use an alternative method to pay, please To change your payment method: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. Select **My account > Payment methods**. 1. **Edit** an existing payment method's information or **Add new payment method**. 1. Select **Save Changes**. @@ -64,7 +81,7 @@ To change your payment method: Automatic renewal of a subscription is charged to your default payment method. To mark a payment method as the default: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. Select **My account > Payment methods**. 1. **Edit** the selected payment method and check the **Make default payment method** checkbox. 1. Select **Save Changes**. @@ -75,10 +92,10 @@ Follow this guideline if you have a legacy Customers Portal account and use an e To link a GitLab.com account to your Customers Portal account: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in?legacy=true) using email and password. +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in?legacy=true) using email and password. 1. On the Customers Portal page, select **My account > Account details**. 1. Under **Your GitLab.com account**, select **Link account**. -1. Log in to the [GitLab.com](https://gitlab.com/users/sign_in) account you want to link to the Customers Portal account. +1. Sign in to the [GitLab.com](https://gitlab.com/users/sign_in) account you want to link to the Customers Portal account. ## Change the linked account @@ -88,17 +105,17 @@ If you have a legacy Customers Portal account that is not linked to a GitLab.com To change the GitLab.com account linked to your Customers Portal account: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. In a separate browser tab, go to [GitLab.com](https://gitlab.com/users/sign_in) and ensure you are not logged in. 1. On the Customers Portal page, select **My account > Account details**. 1. Under **Your GitLab.com account**, select **Change linked account**. -1. Log in to the [GitLab.com](https://gitlab.com/users/sign_in) account you want to link to the Customers Portal account. +1. Sign in to the [GitLab.com](https://gitlab.com/users/sign_in) account you want to link to the Customers Portal account. ## Change Customers Portal account password To change the password for this customers portal account: -1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). +1. Sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in). 1. Select the **My account** dropdown list and select **Account details**. 1. Make the required changes to the **Your password** section. 1. Select **Save changes**. diff --git a/lib/gitlab/database/ci_builds_partitioning.rb b/lib/gitlab/database/ci_builds_partitioning.rb deleted file mode 100644 index a8a935b8c39..00000000000 --- a/lib/gitlab/database/ci_builds_partitioning.rb +++ /dev/null @@ -1,115 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - class CiBuildsPartitioning - include AsyncDdlExclusiveLeaseGuard - - ATTEMPTS = 5 - LOCK_TIMEOUT = 10.seconds - LEASE_TIMEOUT = 20.minutes - - def initialize(logger: Gitlab::AppLogger) - @connection = ::Ci::ApplicationRecord.connection - @timing_configuration = Array.new(ATTEMPTS) { [LOCK_TIMEOUT, 3.minutes] } - @logger = logger - end - - def execute - return unless can_execute? - - try_obtain_lease do - lock_retries.run(raise_on_exhaustion: true) do - connection.execute(create_foreign_key_sql) - end - - log_info('Foreign key successfully created') - end - - rescue StandardError => e - log_info("Failed to create foreign key: #{e.message}") - end - - private - - attr_reader :connection, :timing_configuration, :logger - - def can_execute? - return false if process_disabled? - return false unless Gitlab.com? - - if foreign_key_exists? - log_info('Foreign key exists, nothing to do') - - return false - end - - if vacuum_running? - log_info('Autovacuum detected') - - return false - end - - true - end - - def process_disabled? - ::Feature.disabled?(:p_ci_builds_metadata_foreign_key) - end - - def foreign_key_exists? - Gitlab::Database::SharedModel.using_connection(connection) do - Gitlab::Database::PostgresForeignKey - .by_constrained_table_name_or_identifier(:p_ci_builds_metadata) - .by_referenced_table_name(:p_ci_builds) - .by_name(:temp_fk_e20479742e_p) - .exists? - end - end - - def vacuum_running? - Gitlab::Database::SharedModel.using_connection(connection) do - Gitlab::Database::PostgresAutovacuumActivity - .wraparound_prevention - .for_tables(%i[ci_builds ci_builds_metadata]) - .any? - end - end - - def lock_retries - Gitlab::Database::WithLockRetries.new( - timing_configuration: timing_configuration, - connection: connection, - logger: logger, - klass: self.class - ) - end - - def create_foreign_key_sql - <<~SQL.squish - SET LOCAL statement_timeout TO '11s'; - - LOCK TABLE ci_builds, p_ci_builds, p_ci_builds_metadata IN ACCESS EXCLUSIVE MODE; - - ALTER TABLE p_ci_builds_metadata - ADD CONSTRAINT temp_fk_e20479742e_p - FOREIGN KEY (partition_id, build_id) - REFERENCES p_ci_builds (partition_id, id) - ON UPDATE CASCADE ON DELETE CASCADE; - SQL - end - - def log_info(message) - logger.info(message: message, class: self.class.to_s) - end - - def connection_db_config - ::Ci::ApplicationRecord.connection_db_config - end - - def lease_timeout - LEASE_TIMEOUT - end - end - end -end diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb index 9c860ebc6aa..4a1b0be848e 100644 --- a/lib/gitlab/database/reindexing.rb +++ b/lib/gitlab/database/reindexing.rb @@ -59,7 +59,6 @@ module Gitlab # most bloated indexes for reindexing. def self.perform_with_heuristic(candidate_indexes = Gitlab::Database::PostgresIndex.reindexing_support, maximum_records: DEFAULT_INDEXES_PER_INVOCATION) IndexSelection.new(candidate_indexes).take(maximum_records).each do |index| - Gitlab::Database::CiBuildsPartitioning.new.execute Coordinator.new(index).perform end end diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index da1676138ec..be47b32ec4f 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -468,35 +468,9 @@ RSpec.describe GraphqlController, feature_category: :integrations do post :execute, params: { query: query, operationName: 'IntrospectionQuery' } end - it 'logs that it will try to hit the cache' do - expect(Gitlab::AppLogger).to receive(:info).with(message: "IntrospectionQueryCache hit") - expect(Gitlab::AppLogger).to receive(:info).with( - message: "IntrospectionQueryCache", - can_use_introspection_query_cache: "true", - query: query.to_s, - variables: "{}", - introspection_query_cache_key: "[\"introspection-query-cache\", \"#{Gitlab.revision}\", false]" - ) - - post :execute, params: { query: query, operationName: 'IntrospectionQuery' } - end - context 'when there is an unknown introspection query' do let(:query) { File.read(Rails.root.join('spec/fixtures/api/graphql/fake_introspection.graphql')) } - it 'logs that it did not try to hit the cache' do - expect(Gitlab::AppLogger).to receive(:info).with(message: "IntrospectionQueryCache miss") - expect(Gitlab::AppLogger).to receive(:info).with( - message: "IntrospectionQueryCache", - can_use_introspection_query_cache: "false", - query: query.to_s, - variables: "{}", - introspection_query_cache_key: "[\"introspection-query-cache\", \"#{Gitlab.revision}\", false]" - ) - - post :execute, params: { query: query, operationName: 'IntrospectionQuery' } - end - it 'does not cache an unknown introspection query' do expect(GitlabSchema).to receive(:execute).exactly(:twice) diff --git a/spec/factories/alert_management/http_integrations.rb b/spec/factories/alert_management/http_integrations.rb index 43cf8b3c6db..1a46215de47 100644 --- a/spec/factories/alert_management/http_integrations.rb +++ b/spec/factories/alert_management/http_integrations.rb @@ -19,12 +19,12 @@ FactoryBot.define do endpoint_identifier { 'legacy' } end - trait :prometheus do - type_identifier { :prometheus } - end - initialize_with { new(**attributes) } - factory :alert_management_prometheus_integration, traits: [:prometheus] + factory :alert_management_prometheus_integration, traits: [:prometheus] do + trait :legacy do + endpoint_identifier { 'legacy-prometheus' } + end + end end end diff --git a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js index edaa96a197a..d40499fae87 100644 --- a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js +++ b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js @@ -49,32 +49,36 @@ describe('Rules item', () => { findRulesWhenSelect().vm.$emit('input', dummyRulesWhen); - expect(wrapper.emitted('update-job')).toHaveLength(1); + expect(wrapper.emitted('update-job')).toHaveLength(2); expect(wrapper.emitted('update-job')[0]).toEqual([ 'rules[0].when', JOB_RULES_WHEN.delayed.value, ]); + expect(wrapper.emitted('update-job')[1]).toEqual([ + 'rules[0].start_in', + `1 ${JOB_RULES_START_IN.second.value}`, + ]); findRulesStartInNumberInput().vm.$emit('input', dummyRulesStartInNumber); - expect(wrapper.emitted('update-job')).toHaveLength(2); - expect(wrapper.emitted('update-job')[1]).toEqual([ + expect(wrapper.emitted('update-job')).toHaveLength(3); + expect(wrapper.emitted('update-job')[2]).toEqual([ 'rules[0].start_in', `2 ${JOB_RULES_START_IN.second.value}s`, ]); findRulesStartInUnitSelect().vm.$emit('input', dummyRulesStartInUnit); - expect(wrapper.emitted('update-job')).toHaveLength(3); - expect(wrapper.emitted('update-job')[2]).toEqual([ + expect(wrapper.emitted('update-job')).toHaveLength(4); + expect(wrapper.emitted('update-job')[3]).toEqual([ 'rules[0].start_in', `2 ${dummyRulesStartInUnit}s`, ]); findRulesAllowFailureCheckBox().vm.$emit('input', dummyRulesAllowFailure); - expect(wrapper.emitted('update-job')).toHaveLength(4); - expect(wrapper.emitted('update-job')[3]).toEqual([ + expect(wrapper.emitted('update-job')).toHaveLength(5); + expect(wrapper.emitted('update-job')[4]).toEqual([ 'rules[0].allow_failure', dummyRulesAllowFailure, ]); diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js index ca0c695481a..a8f7165000d 100644 --- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js +++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js @@ -1,4 +1,4 @@ -import { mount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; import { @@ -18,10 +18,6 @@ import RelatedIssuesBlock from '~/related_issues/components/related_issues_block import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue'; jest.mock('~/alert'); -// TODO: This suite is flaky with the default timeout, so -// double it. Improve the test or component to avoid this. -// See https://gitlab.com/gitlab-org/gitlab/-/issues/417175. -jest.setTimeout(10_000); describe('RelatedIssuesRoot', () => { let wrapper; @@ -39,7 +35,7 @@ describe('RelatedIssuesRoot', () => { }); const createComponent = ({ props = {}, data = {} } = {}) => { - wrapper = mount(RelatedIssuesRoot, { + wrapper = shallowMount(RelatedIssuesRoot, { propsData: { ...defaultProps, ...props, diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js index 1285404fd9f..fa188f50d54 100644 --- a/spec/frontend/members/components/table/role_dropdown_spec.js +++ b/spec/frontend/members/components/table/role_dropdown_spec.js @@ -238,6 +238,16 @@ describe('RoleDropdown', () => { it('does not call updateMemberRole', () => { expect(actions.updateMemberRole).not.toHaveBeenCalled(); }); + + it('re-enables dropdown', async () => { + await waitForPromises(); + + expect(findListbox().props('disabled')).toBe(false); + }); + + it('resets selected dropdown item', () => { + expect(findListbox().props('selected')).toBe(member.validRoles.Owner); + }); }); }); }); diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js index 784a8dec975..b84d1c9c0aa 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js @@ -80,7 +80,7 @@ describe('ServiceDeskRoot', () => { const alertBodyLink = alertEl.findComponent(GlLink); expect(alertBodyLink.exists()).toBe(true); expect(alertBodyLink.attributes('href')).toBe( - '/help/user/project/service_desk.html#use-a-custom-email-address', + '/help/user/project/service_desk.html#use-an-additional-service-desk-alias-email', ); expect(alertBodyLink.text()).toBe('How do I create a custom email address?'); }); diff --git a/spec/models/alert_management/http_integration_spec.rb b/spec/models/alert_management/http_integration_spec.rb index 606b53aeacd..48daef894a8 100644 --- a/spec/models/alert_management/http_integration_spec.rb +++ b/spec/models/alert_management/http_integration_spec.rb @@ -90,7 +90,7 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man describe 'scopes' do let_it_be(:integration_1) { create(:alert_management_http_integration) } let_it_be(:integration_2) { create(:alert_management_http_integration, :inactive, project: project) } - let_it_be(:integration_3) { create(:alert_management_http_integration, :prometheus, project: project) } + let_it_be(:integration_3) { create(:alert_management_prometheus_integration, project: project) } let_it_be(:integration_4) { create(:alert_management_http_integration, :legacy, :inactive) } describe '.for_endpoint_identifier' do @@ -129,12 +129,6 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man it { is_expected.to contain_exactly(integration_1, integration_3) } end - describe '.legacy' do - subject { described_class.legacy } - - it { is_expected.to contain_exactly(integration_4) } - end - describe '.ordered_by_type_and_id' do before do # Rearrange cache by saving to avoid false-positives @@ -232,9 +226,16 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man end context 'when included in initialization args' do - let(:integration) { described_class.new(endpoint_identifier: 'legacy') } + let(:required_args) { { project: project, name: 'Name' } } - it { is_expected.to eq('legacy') } + AlertManagement::HttpIntegration::LEGACY_IDENTIFIERS.each do |identifier| + context "for endpoint identifier \"#{identifier}\"" do + let(:integration) { described_class.new(**required_args, endpoint_identifier: identifier) } + + it { is_expected.to eq(identifier) } + specify { expect(integration).to be_valid } + end + end end context 'when reassigning' do @@ -293,7 +294,7 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man end context 'for a prometheus integration' do - let(:integration) { build(:alert_management_http_integration, :prometheus) } + let(:integration) { build(:alert_management_prometheus_integration) } it do is_expected.to eq( @@ -307,7 +308,7 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man end context 'for a legacy integration' do - let(:integration) { build(:alert_management_http_integration, :prometheus, :legacy) } + let(:integration) { build(:alert_management_prometheus_integration, :legacy) } it do is_expected.to eq( diff --git a/spec/requests/verifies_with_email_spec.rb b/spec/requests/verifies_with_email_spec.rb index 6325ecc1184..f3f8e4a1a83 100644 --- a/spec/requests/verifies_with_email_spec.rb +++ b/spec/requests/verifies_with_email_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_redis_rate_limiting, -feature_category: :user_management do + feature_category: :instance_resiliency do include SessionHelpers include EmailHelpers diff --git a/spec/services/clusters/agent_tokens/create_service_spec.rb b/spec/services/clusters/agent_tokens/create_service_spec.rb index 431d7ce2079..fde39b1099e 100644 --- a/spec/services/clusters/agent_tokens/create_service_spec.rb +++ b/spec/services/clusters/agent_tokens/create_service_spec.rb @@ -89,21 +89,6 @@ RSpec.describe Clusters::AgentTokens::CreateService, feature_category: :deployme expect(subject.status).to eq(:error) expect(subject.message).to eq('An agent can have only two active tokens at a time') end - - context 'when cluster_agents_limit_tokens_created feature flag is disabled' do - before do - stub_feature_flags(cluster_agents_limit_tokens_created: false) - end - - it 'creates a new token' do - expect { subject }.to change { ::Clusters::AgentToken.count }.by(1) - end - - it 'returns success status', :aggregate_failures do - expect(subject.status).to eq(:success) - expect(subject.message).to be_nil - end - end end end end diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb index a12d86412d8..d0fca2a5f08 100644 --- a/spec/services/packages/npm/create_package_service_spec.rb +++ b/spec/services/packages/npm/create_package_service_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Packages::Npm::CreatePackageService, feature_category: :package_r let(:namespace) { create(:namespace) } let(:project) { create(:project, namespace: namespace) } - let(:user) { create(:user) } + let(:user) { project.owner } let(:version) { '1.0.1' } let(:params) do @@ -171,6 +171,12 @@ RSpec.describe Packages::Npm::CreatePackageService, feature_category: :package_r it_behaves_like 'valid package' end + context 'when user is no project member' do + let(:user) { create(:user) } + + it_behaves_like 'valid package' + end + context 'scoped package not following the naming convention' do let(:package_name) { '@any-scope/package' } diff --git a/workhorse/go.mod b/workhorse/go.mod index 000593c6025..61c443399a8 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -6,7 +6,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 github.com/BurntSushi/toml v1.3.0 github.com/FZambia/sentinel v1.1.1 - github.com/alecthomas/chroma/v2 v2.7.0 + github.com/alecthomas/chroma/v2 v2.8.0 github.com/aws/aws-sdk-go v1.44.256 github.com/disintegration/imaging v1.6.2 github.com/getsentry/raven-go v0.2.0 diff --git a/workhorse/go.sum b/workhorse/go.sum index 03b95b15274..f0510497de2 100644 --- a/workhorse/go.sum +++ b/workhorse/go.sum @@ -537,8 +537,8 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= -github.com/alecthomas/chroma/v2 v2.7.0 h1:hm1rY6c/Ob4eGclpQ7X/A3yhqBOZNUTk9q+yhyLIViI= -github.com/alecthomas/chroma/v2 v2.7.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw= +github.com/alecthomas/chroma/v2 v2.8.0 h1:w9WJUjFFmHHB2e8mRpL9jjy3alYDlU0QLDezj1xE264= +github.com/alecthomas/chroma/v2 v2.8.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= |