Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/policies/project_policy.rb2
-rw-r--r--app/views/groups/settings/_permissions.html.haml1
-rw-r--r--app/workers/concerns/application_worker.rb1
-rw-r--r--changelogs/unreleased/216987-prevent-forking-outside-a-group.yml5
-rw-r--r--changelogs/unreleased/225219-add-nuget-lock-file-to-gemnasium-job.yml5
-rw-r--r--changelogs/unreleased/mwaw-218861-enable-read-pod-logs-to-developer-access-lvl.yml6
-rw-r--r--config/feature_flags/development/sidekiq_versioning.yml7
-rw-r--r--db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb9
-rw-r--r--db/schema_migrations/202007170802571
-rw-r--r--db/structure.sql3
-rw-r--r--doc/api/groups.md1
-rw-r--r--doc/development/geo/framework.md100
-rw-r--r--doc/development/sidekiq_style_guide.md30
-rw-r--r--doc/user/group/index.md17
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/project/repository/repository_mirroring.md85
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml1
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb2
-rw-r--r--lib/gitlab/set_cache.rb14
-rw-r--r--lib/gitlab/sidekiq_middleware.rb1
-rw-r--r--lib/gitlab/sidekiq_versioning/middleware.rb13
-rw-r--r--lib/gitlab/sidekiq_versioning/worker.rb31
-rw-r--r--lib/gitlab/usage_data/topology.rb18
-rw-r--r--locale/gitlab.pot21
-rw-r--r--package.json4
-rw-r--r--spec/controllers/projects/logs_controller_spec.rb25
-rw-r--r--spec/factories/namespace_settings.rb7
-rw-r--r--spec/factories/namespaces.rb4
-rw-r--r--spec/lib/gitlab/middleware/read_only_spec.rb13
-rw-r--r--spec/lib/gitlab/repository_set_cache_spec.rb17
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb38
-rw-r--r--spec/lib/gitlab/sidekiq_versioning/middleware_spec.rb60
-rw-r--r--spec/lib/gitlab/sidekiq_versioning/worker_spec.rb54
-rw-r--r--spec/policies/project_policy_spec.rb2
-rw-r--r--spec/requests/api/pypi_packages_spec.rb312
-rw-r--r--spec/serializers/environment_entity_spec.rb8
-rw-r--r--yarn.lock4
38 files changed, 696 insertions, 230 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 41652a6743b..131deea6e8b 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-a6091637dcb4c3b601a8860b5f164c0ce90ba0ca
+d02d473234dc18649e5a359ee203d6a3aa5c4031
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 41274fe9db4..bdfad994d55 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -328,6 +328,7 @@ class ProjectPolicy < BasePolicy
enable :move_design
enable :destroy_design
enable :read_terraform_state
+ enable :read_pod_logs
end
rule { can?(:developer_access) & user_confirmed? }.policy do
@@ -367,7 +368,6 @@ class ProjectPolicy < BasePolicy
enable :admin_operations
enable :read_deploy_token
enable :create_deploy_token
- enable :read_pod_logs
enable :destroy_deploy_token
enable :read_prometheus_alerts
enable :admin_terraform_state
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index 507246d573e..74d6c3f01dd 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -37,6 +37,7 @@
= render 'groups/settings/default_branch_protection', f: f, group: @group
= render 'groups/settings/project_creation_level', f: f, group: @group
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
+ = render_if_exists 'groups/settings/prevent_forking', f: f, group: @group
= render 'groups/settings/two_factor_auth', f: f
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 9c942228111..30dec5159a2 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -10,6 +10,7 @@ module ApplicationWorker
include Sidekiq::Worker # rubocop:disable Cop/IncludeSidekiqWorker
include WorkerAttributes
include WorkerContext
+ include Gitlab::SidekiqVersioning::Worker
LOGGING_EXTRA_KEY = 'extra'
diff --git a/changelogs/unreleased/216987-prevent-forking-outside-a-group.yml b/changelogs/unreleased/216987-prevent-forking-outside-a-group.yml
new file mode 100644
index 00000000000..f2cdd400c81
--- /dev/null
+++ b/changelogs/unreleased/216987-prevent-forking-outside-a-group.yml
@@ -0,0 +1,5 @@
+---
+title: Add Prevent forking outside group feature
+merge_request: 36848
+author:
+type: added
diff --git a/changelogs/unreleased/225219-add-nuget-lock-file-to-gemnasium-job.yml b/changelogs/unreleased/225219-add-nuget-lock-file-to-gemnasium-job.yml
new file mode 100644
index 00000000000..37c85ba1cae
--- /dev/null
+++ b/changelogs/unreleased/225219-add-nuget-lock-file-to-gemnasium-job.yml
@@ -0,0 +1,5 @@
+---
+title: "Add NuGet lock files support to Dependency Scanning CI template"
+merge_request: 37553
+author:
+type: added
diff --git a/changelogs/unreleased/mwaw-218861-enable-read-pod-logs-to-developer-access-lvl.yml b/changelogs/unreleased/mwaw-218861-enable-read-pod-logs-to-developer-access-lvl.yml
new file mode 100644
index 00000000000..b47c3964194
--- /dev/null
+++ b/changelogs/unreleased/mwaw-218861-enable-read-pod-logs-to-developer-access-lvl.yml
@@ -0,0 +1,6 @@
+---
+title: Allow users with developer access level for given project to view kubernetes
+ pod logs
+merge_request: 38467
+author:
+type: changed
diff --git a/config/feature_flags/development/sidekiq_versioning.yml b/config/feature_flags/development/sidekiq_versioning.yml
new file mode 100644
index 00000000000..76b6e63adaa
--- /dev/null
+++ b/config/feature_flags/development/sidekiq_versioning.yml
@@ -0,0 +1,7 @@
+---
+name: sidekiq_versioning
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232934
+group: group::fulfillment
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb b/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb
new file mode 100644
index 00000000000..b46daac6a98
--- /dev/null
+++ b/db/migrate/20200717080257_add_prevent_forking_to_namespace_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddPreventForkingToNamespaceSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :namespace_settings, :prevent_forking_outside_group, :boolean, null: false, default: false
+ end
+end
diff --git a/db/schema_migrations/20200717080257 b/db/schema_migrations/20200717080257
new file mode 100644
index 00000000000..73a5b583f8a
--- /dev/null
+++ b/db/schema_migrations/20200717080257
@@ -0,0 +1 @@
+dbb84d05cfe6d2ef143b9321b2b089c66d705f01ced64756032622f64f8e3eed \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 983a61c7b48..4068d89205d 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13257,7 +13257,8 @@ CREATE TABLE public.namespace_root_storage_statistics (
CREATE TABLE public.namespace_settings (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- namespace_id integer NOT NULL
+ namespace_id integer NOT NULL,
+ prevent_forking_outside_group boolean DEFAULT false NOT NULL
);
CREATE TABLE public.namespace_statistics (
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 28f242b083b..82ee2fb1db5 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -750,6 +750,7 @@ PUT /groups/:id
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
| `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
| `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces
NOTE: **Note:**
The `projects` and `shared_projects` attributes in the response are deprecated and will be [removed in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 040c53e4c79..64c9030e3dd 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -219,10 +219,30 @@ For example, to add support for files referenced by a `Widget` model with a
def carrierwave_uploader
model_record.file
end
+
+ # Change this to `true` to release replication of this model. Then remove
+ # this override in the next release.
+ # The feature flag follows the format `geo_#{replicable_name}_replication`,
+ # so here it would be `geo_widget_replication`
+ def self.replication_enabled_by_default?
+ false
+ end
end
end
```
+1. Add this replicator class to the method `replicator_classes` in
+`ee/lib/gitlab/geo.rb`:
+
+ ```ruby
+ def self.replicator_classes
+ classes = [::Geo::PackageFileReplicator,
+ ::Geo::WidgetReplicator]
+
+ classes.select(&:enabled?)
+ end
+ ```
+
1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
the setup necessary to define the `model_record` variable for the shared
examples.
@@ -239,13 +259,15 @@ For example, to add support for files referenced by a `Widget` model with a
end
```
-1. Create the `widget_registry` table so Geo secondaries can track the sync and
+1. Create the `widget_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and
verification state of each Widget's file. This migration belongs in `ee/db/geo/migrate`:
```ruby
# frozen_string_literal: true
class CreateWidgetRegistry < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
disable_ddl_transaction!
@@ -257,12 +279,12 @@ For example, to add support for files referenced by a `Widget` model with a
t.integer :widget_id, null: false
t.integer :state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2
- t.text :last_sync_failure
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :created_at, null: false
+ t.text :last_sync_failure
- t.index :widget_id
+ t.index :widget_id, name: :index_widget_registry_on_widget_id
t.index :retry_at
t.index :state
end
@@ -358,8 +380,13 @@ Widgets should now be replicated by Geo!
#### Verification
-1. Add verification state fields to the `widgets` table so the Geo primary can
- track verification state:
+There are two ways to add verification related fields so that the Geo primary
+can track verification state:
+
+##### Option 1: Add verification state fields to the existing `widgets` table itself
+
+1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
+for verification state to the widgets table:
```ruby
# frozen_string_literal: true
@@ -382,7 +409,7 @@ Widgets should now be replicated by Geo!
end
```
- Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
+1. Adding a `text` column also [requires](../database/strings_and_the_text_data_type.md#add-a-text-column-to-an-existing-table)
setting a limit:
```ruby
@@ -400,7 +427,7 @@ Widgets should now be replicated by Geo!
```
1. Add a partial index on `verification_failure` and `verification_checksum` to ensure
- re-verification can be performed efficiently:
+ re-verification can be performed efficiently. Add a migration in `ee/db/geo/migrate/`:
```ruby
# frozen_string_literal: true
@@ -424,6 +451,65 @@ Widgets should now be replicated by Geo!
end
```
+##### Option 2: Create a separate `widget_states` table with verification state fields
+
+1. Add a migration in `ee/db/geo/migrate/` to create a `widget_states` table and add a
+ partial index on `verification_failure` and `verification_checksum` to ensure
+ re-verification can be performed efficiently. Order the columns according to [our guidelines](../ordering_table_columns.md):
+
+ ```ruby
+ # frozen_string_literal: true
+
+ class CreateWidgetStates < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:widget_states)
+ with_lock_retries do
+ create_table :widget_states, id: false do |t|
+ t.references :widget, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure
+
+ t.index :verification_failure, where: "(verification_failure IS NOT NULL)", name: "widgets_verification_failure_partial"
+ t.index :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: "widgets_verification_checksum_partial"
+ end
+ end
+ end
+
+ add_text_limit :widget_states, :verification_failure, 255
+ end
+
+ def down
+ drop_table :widget_states
+ end
+ end
+ ```
+
+1. Add the following lines to the `widget` model:
+
+ ```ruby
+ class Widget < ApplicationRecord
+ ...
+ has_one :widget_state, inverse_of: :widget
+
+ delegate :verification_retry_at, :verification_retry_at=,
+ :verified_at, :verified_at=,
+ :verification_checksum, :verification_checksum=,
+ :verification_failure, :verification_failure=,
+ :verification_retry_count, :verification_retry_count=,
+ to: :widget_state
+ ...
+ end
+ ```
+
To do: Add verification on secondaries. This should be done as part of
[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index c453b189395..c5dfc5731e6 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -64,6 +64,36 @@ the extra jobs will take resources away from jobs from workers that were already
there, if the resources available to the Sidekiq process handling the namespace
are not adjusted appropriately.
+## Versioning
+
+Version can be specified on each Sidekiq worker class.
+This is then sent along when the job is created.
+
+```ruby
+class FooWorker
+ include ApplicationWorker
+
+ version 2
+
+ def perform(*args)
+ if job_version == 2
+ foo = args.first['foo']
+ else
+ foo = args.first
+ end
+ end
+end
+```
+
+Under this schema, any worker is expected to be able to handle any job that was
+enqueued by an older version of that worker. This means that when changing the
+arguments a worker takes, you must increment the `version` (or set `version 1`
+if this is the first time a worker's arguments are changing), but also make sure
+that the worker is still able to handle jobs that were queued with any earlier
+version of the arguments. From the worker's `perform` method, you can read
+`self.job_version` if you want to specifically branch on job version, or you
+can read the number or type of provided arguments.
+
## Idempotent Jobs
It's known that a job can fail for multiple reasons. For example, network outages or bugs.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index b58ea801557..cad74900f16 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -668,6 +668,23 @@ To enable delayed deletion of projects:
1. Expand the **Permissions, LFS, 2FA** section, and check **Enable delayed project removal**.
1. Click **Save changes**.
+#### Prevent project forking outside group **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
+
+By default, projects within a group can be forked.
+Optionally, on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
+you can prevent the projects within a group from being forked outside of the current top-level group.
+
+Previously this setting was available only for groups enforcing group managed account. This setting will be
+removed from SAML setting page and migrated to group setting, but in the interim period of changes both of those settings will be taken into consideration, if even one is set to `true` then it will be assumed group does not allow forking projects outside.
+
+To enable prevent project forking:
+
+1. Navigate to the top-level group's **Settings > General** page.
+1. Expand the **Permissions, LFS, 2FA** section, and check **Prevent project forking outside current group**.
+1. Click **Save changes**.
+
### Advanced settings
- **Projects**: View all projects within that group, add members to each project,
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 037711aff30..aeb383bdc6b 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -142,7 +142,7 @@ The following table depicts the various user permission levels in a project.
| Remove GitLab Pages | | | | ✓ | ✓ |
| Manage clusters | | | | ✓ | ✓ |
| Manage Project Operations | | | | ✓ | ✓ |
-| View Pods logs | | | | ✓ | ✓ |
+| View Pods logs | | | ✓ | ✓ | ✓ |
| Read Terraform state | | | ✓ | ✓ | ✓ |
| Manage Terraform state | | | | ✓ | ✓ |
| Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ |
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index fc6411ea319..406606b385e 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -3,6 +3,9 @@ stage: Create
group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.html'
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Repository mirroring
@@ -124,7 +127,87 @@ To set up a mirror from GitLab to GitHub, you need to follow these steps:
The mirrored repository will be listed. For example, `https://*****:*****@github.com/<your_github_group>/<your_github_project>.git`.
-The repository will push soon. To force a push, click the appropriate button.
+The repository will push soon. To force a push, click the **Update now** (**{retry}**) button.
+
+## Setting up a push mirror from GitLab to AWS CodeCommit
+
+AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab is not yet supported as one of their Source Code Management (SCM) providers.
+
+Each new AWS Codepipeline needs significant AWS infrastructure setup. It also requires an individual pipeline per branch.
+
+If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage GitLab CI/CD pipelines and simply use the AWS CLI in the final job in `.gitlab-ci.yml` to deploy to CodeDeploy.
+
+NOTE: **Note:**
+GitLab-to-AWS-CodeCommit push mirroring cannot use SSH authentication until [GitLab issue 34014](https://gitlab.com/gitlab-org/gitlab/-/issues/34014) is resolved.
+
+To set up a mirror from GitLab to AWS CodeCommit:
+
+1. In the AWS IAM console, create an IAM user.
+1. Add the following least privileges permissions for repository mirroring as an "inline policy".
+
+ The Amazon Resource Names (ARNs) must explicitly include the region and account. The IAM policy
+ below grants privilege for mirroring access to two sample repositories. These permissions have
+ been tested to be the minimum (least privileged) required for mirroring:
+
+ ```json
+
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "MinimumGitLabPushMirroringPermissions",
+ "Effect": "Allow",
+ "Action": [
+ "codecommit:GitPull",
+ "codecommit:GitPush"
+ ],
+ "Resource": [
+ "arn:aws:codecommit:us-east-1:111111111111:MyDestinationRepo",
+ "arn:aws:codecommit:us-east-1:111111111111:MyDemo*"
+ ]
+ }
+ ]
+ }
+
+ ```json
+
+1. After the user was created, click the AWS IAM user name.
+1. Click the **Security credentials** tab.
+1. Under **HTTPS Git credentials for AWS CodeCommit** click **Generate credentials**.
+
+ NOTE: **Note:**
+ This Git user ID and password is specific to communicating with CodeCommit. Do
+ not confuse it with the IAM user ID or AWS keys of this user.
+
+1. Copy or download special Git HTTPS user ID and password.
+1. In the AWS CodeCommit console, create a new repository to mirror from your GitLab repo.
+1. Open your new repository and click **Clone URL > Clone HTTPS** (not **Clone HTTPS (GRC)**).
+1. In GitLab, open the repository to be push-mirrored.
+1. Click **Settings > Repository** and expand **Mirroring repositories**.
+1. Fill in the **Git repository URL** field using this format:
+
+ ```plaintext
+ https://<your_aws_git_userid>@git-codecommit.<aws-region>.amazonaws.com/v1/repos/<your_codecommit_repo>
+ ```
+
+ Replace `<your_aws_git_userid>` with the AWS **special HTTPS Git user ID** from the IAM Git
+ credentials created earlier. Replace `<your_codecommit_repo>` with the name of your repo in CodeCommit.
+
+1. For **Mirror direction**, select **Push**.
+1. For **Authentication method**, select **Password** and fill in the **Password** field with the special IAM Git clone user ID **password** created earlier in AWS.
+1. The option **Only mirror protected branches** should be good for CodeCommit as it pushes more
+ frequently (from every five minutes to every minute).
+ CodePipeline requires individual pipeline setups for named branches you wish to have a AWS CI setup for. Since feature branches that have dynamic names will not be supported anyway, configuring **Only mirror protected branches** does not cause flexibility problems with CodePipeline integration as long as you are also willing to protect all the named branches you want to build CodePipelines for.
+
+1. Click **Mirror repository**. You should see the mirrored repository appear:
+
+ ```plaintext
+ https://*****:*****@git-codecommit.<aws-region>.amazonaws.com/v1/repos/<your_codecommit_repo>
+ ```
+
+To test mirroring by forcing a push, click the half-circle arrows button (hover text is **Update now**).
+If **Last successful update** shows a date, you have configured mirroring correctly.
+If it is not working correctly a red `error` tag appears and shows the error message as hover text.
## Setting up a push mirror to another GitLab instance with 2FA activated
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index 4c4ae4f69fd..d5275c57ef8 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -111,6 +111,7 @@ gemnasium-dependency_scanning:
- '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
+ - '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
gemnasium-maven-dependency_scanning:
extends: .ds-analyzer
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 1c49379e8d2..6573506e926 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -136,7 +136,7 @@ module Gitlab
end
def graphql_query?
- request.post? && request.path.start_with?(GRAPHQL_URL)
+ request.post? && request.path.start_with?(File.join(relative_url, GRAPHQL_URL))
end
end
end
diff --git a/lib/gitlab/set_cache.rb b/lib/gitlab/set_cache.rb
index 6ba9ee26634..591265d014e 100644
--- a/lib/gitlab/set_cache.rb
+++ b/lib/gitlab/set_cache.rb
@@ -22,7 +22,7 @@ module Gitlab
keys = keys.map { |key| cache_key(key) }
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
- unlink_or_delete(redis, keys)
+ redis.unlink(*keys)
end
end
end
@@ -60,17 +60,5 @@ module Gitlab
def with(&blk)
Gitlab::Redis::Cache.with(&blk) # rubocop:disable CodeReuse/ActiveRecord
end
-
- def unlink_or_delete(redis, keys)
- if Feature.enabled?(:repository_set_cache_unlink, default_enabled: true)
- redis.unlink(*keys)
- else
- redis.del(*keys)
- end
- rescue ::Redis::CommandError => e
- Gitlab::ErrorTracking.log_exception(e)
-
- redis.del(*keys)
- end
end
end
diff --git a/lib/gitlab/sidekiq_middleware.rb b/lib/gitlab/sidekiq_middleware.rb
index 4eef3fbd12e..5f912818605 100644
--- a/lib/gitlab/sidekiq_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware.rb
@@ -19,6 +19,7 @@ module Gitlab
chain.add ::Labkit::Middleware::Sidekiq::Server
chain.add ::Gitlab::SidekiqMiddleware::InstrumentationLogger
chain.add ::Gitlab::SidekiqMiddleware::AdminMode::Server
+ chain.add ::Gitlab::SidekiqVersioning::Middleware
chain.add ::Gitlab::SidekiqStatus::ServerMiddleware
chain.add ::Gitlab::SidekiqMiddleware::WorkerContext::Server
chain.add ::Gitlab::SidekiqMiddleware::DuplicateJobs::Server
diff --git a/lib/gitlab/sidekiq_versioning/middleware.rb b/lib/gitlab/sidekiq_versioning/middleware.rb
new file mode 100644
index 00000000000..e2d692c619b
--- /dev/null
+++ b/lib/gitlab/sidekiq_versioning/middleware.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqVersioning
+ class Middleware
+ def call(worker, job, queue)
+ worker.job_version = job['version'] if worker.is_a?(ApplicationWorker) && Feature.enabled?(:sidekiq_versioning)
+
+ yield
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_versioning/worker.rb b/lib/gitlab/sidekiq_versioning/worker.rb
new file mode 100644
index 00000000000..fe9bae6b8a1
--- /dev/null
+++ b/lib/gitlab/sidekiq_versioning/worker.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqVersioning
+ module Worker
+ extend ActiveSupport::Concern
+
+ included do
+ version 0
+
+ attr_writer :job_version
+ end
+
+ class_methods do
+ def version(new_version = nil)
+ if new_version
+ sidekiq_options version: new_version.to_i
+ else
+ get_sidekiq_options['version']
+ end
+ end
+ end
+
+ # Version is not set if `new.perform` is called directly,
+ # and in that case we fallback to latest version
+ def job_version
+ @job_version ||= self.class.version
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data/topology.rb b/lib/gitlab/usage_data/topology.rb
index 4105a838df7..9a1c03173eb 100644
--- a/lib/gitlab/usage_data/topology.rb
+++ b/lib/gitlab/usage_data/topology.rb
@@ -51,7 +51,7 @@ module Gitlab
def topology_app_requests_per_hour(client)
result = query_safely('gitlab_usage_ping:ops:rate5m', 'app_requests', fallback: nil) do |query|
- client.query(one_week_average(query)).first
+ client.query(aggregate_one_week(query)).first
end
return unless result
@@ -84,14 +84,14 @@ module Gitlab
end
def topology_node_memory(client)
- query_safely('gitlab_usage_ping:node_memory_total_bytes:avg', 'node_memory', fallback: {}) do |query|
- aggregate_by_instance(client, one_week_average(query))
+ query_safely('gitlab_usage_ping:node_memory_total_bytes:max', 'node_memory', fallback: {}) do |query|
+ aggregate_by_instance(client, aggregate_one_week(query, aggregation: :max))
end
end
def topology_node_cpus(client)
query_safely('gitlab_usage_ping:node_cpus:count', 'node_cpus', fallback: {}) do |query|
- aggregate_by_instance(client, one_week_average(query, aggregation: :max))
+ aggregate_by_instance(client, aggregate_one_week(query, aggregation: :max))
end
end
@@ -114,25 +114,25 @@ module Gitlab
def topology_service_memory_rss(client)
query_safely(
'gitlab_usage_ping:node_service_process_resident_memory_bytes:avg', 'service_rss', fallback: {}
- ) { |query| aggregate_by_labels(client, one_week_average(query)) }
+ ) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_service_memory_uss(client)
query_safely(
'gitlab_usage_ping:node_service_process_unique_memory_bytes:avg', 'service_uss', fallback: {}
- ) { |query| aggregate_by_labels(client, one_week_average(query)) }
+ ) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_service_memory_pss(client)
query_safely(
'gitlab_usage_ping:node_service_process_proportional_memory_bytes:avg', 'service_pss', fallback: {}
- ) { |query| aggregate_by_labels(client, one_week_average(query)) }
+ ) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_all_service_process_count(client)
query_safely(
'gitlab_usage_ping:node_service_process:count', 'service_process_count', fallback: {}
- ) { |query| aggregate_by_labels(client, one_week_average(query)) }
+ ) { |query| aggregate_by_labels(client, aggregate_one_week(query)) }
end
def topology_all_service_server_types(client)
@@ -231,7 +231,7 @@ module Gitlab
end
end
- def one_week_average(query, aggregation: :avg)
+ def aggregate_one_week(query, aggregation: :avg)
"#{aggregation}_over_time (#{query}[1w])"
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fe3ece1a65c..f46256aec37 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -10336,6 +10336,9 @@ msgstr ""
msgid "FeatureFlags|New feature flag"
msgstr ""
+msgid "FeatureFlags|New list"
+msgstr ""
+
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr ""
@@ -12019,6 +12022,12 @@ msgstr ""
msgid "GroupSettings|Please choose a group URL with no special characters."
msgstr ""
+msgid "GroupSettings|Prevent forking outside of the group"
+msgstr ""
+
+msgid "GroupSettings|Prevent forking setting was not saved"
+msgstr ""
+
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
@@ -12055,6 +12064,9 @@ msgstr ""
msgid "GroupSettings|This setting will prevent group members from being notified if the group is mentioned."
msgstr ""
+msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
+msgstr ""
+
msgid "GroupSettings|Transfer group"
msgstr ""
@@ -17935,6 +17947,9 @@ msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr ""
+msgid "Prevent project forking outside current group"
+msgstr ""
+
msgid "Prevent users from changing their profile name"
msgstr ""
@@ -26211,9 +26226,6 @@ msgstr ""
msgid "User List"
msgstr ""
-msgid "User Lists can only be created and modified with %{linkStart}the API%{linkEnd}"
-msgstr ""
-
msgid "User OAuth applications"
msgstr ""
@@ -26283,6 +26295,9 @@ msgstr ""
msgid "UserLists|Define a set of users to be used within feature flag strategies"
msgstr ""
+msgid "UserLists|Edit"
+msgstr ""
+
msgid "UserLists|Edit %{name}"
msgstr ""
diff --git a/package.json b/package.json
index 8fe3070f6e9..c16ead2b10f 100644
--- a/package.json
+++ b/package.json
@@ -161,7 +161,7 @@
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
"@gitlab/eslint-plugin": "3.1.0",
"@testing-library/dom": "^7.16.2",
- "@vue/test-utils": "^1.0.0-beta.30",
+ "@vue/test-utils": "1.0.0-beta.30",
"acorn": "^6.3.0",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^24.1.0",
@@ -211,7 +211,7 @@
"stylelint-config-recommended": "^2.2.0",
"stylelint-scss": "^3.9.2",
"timezone-mock": "^1.0.8",
- "vue-jest": "^4.0.0-beta.2",
+ "vue-jest": "4.0.0-beta.2",
"webpack-dev-server": "^3.10.3",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
diff --git a/spec/controllers/projects/logs_controller_spec.rb b/spec/controllers/projects/logs_controller_spec.rb
index 0f34e536064..013155b4649 100644
--- a/spec/controllers/projects/logs_controller_spec.rb
+++ b/spec/controllers/projects/logs_controller_spec.rb
@@ -22,8 +22,8 @@ RSpec.describe Projects::LogsController do
describe 'GET #index' do
let(:empty_project) { create(:project) }
- it 'returns 404 with developer access' do
- project.add_developer(user)
+ it 'returns 404 with reporter access' do
+ project.add_reporter(user)
get :index, params: environment_params
@@ -31,7 +31,7 @@ RSpec.describe Projects::LogsController do
end
it 'renders empty logs page if no environment exists' do
- empty_project.add_maintainer(user)
+ empty_project.add_developer(user)
get :index, params: { namespace_id: empty_project.namespace, project_id: empty_project }
@@ -40,7 +40,7 @@ RSpec.describe Projects::LogsController do
end
it 'renders index template' do
- project.add_maintainer(user)
+ project.add_developer(user)
get :index, params: environment_params
@@ -69,14 +69,27 @@ RSpec.describe Projects::LogsController do
end
end
- it 'returns 404 with developer access' do
- project.add_developer(user)
+ it 'returns 404 with reporter access' do
+ project.add_reporter(user)
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
expect(response).to have_gitlab_http_status(:not_found)
end
+ context 'with developer access' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns the service result' do
+ get endpoint, params: environment_params(pod_name: pod_name, format: :json)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to eq(service_result_json)
+ end
+ end
+
context 'with maintainer access' do
before do
project.add_maintainer(user)
diff --git a/spec/factories/namespace_settings.rb b/spec/factories/namespace_settings.rb
new file mode 100644
index 00000000000..388ea7dab91
--- /dev/null
+++ b/spec/factories/namespace_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :namespace_settings, class: 'NamespaceSetting' do
+ namespace
+ end
+end
diff --git a/spec/factories/namespaces.rb b/spec/factories/namespaces.rb
index f4d5848e878..0dcec086da9 100644
--- a/spec/factories/namespaces.rb
+++ b/spec/factories/namespaces.rb
@@ -30,6 +30,10 @@ FactoryBot.define do
association :root_storage_statistics, factory: :namespace_root_storage_statistics
end
+ trait :with_namespace_settings do
+ association :namespace_settings, factory: :namespace_settings
+ end
+
# Construct a hierarchy underneath the namespace.
# Each namespace will have `children` amount of children,
# and `depth` levels of descendants.
diff --git a/spec/lib/gitlab/middleware/read_only_spec.rb b/spec/lib/gitlab/middleware/read_only_spec.rb
index 3bdf2a5077f..50dd38278b9 100644
--- a/spec/lib/gitlab/middleware/read_only_spec.rb
+++ b/spec/lib/gitlab/middleware/read_only_spec.rb
@@ -110,6 +110,19 @@ RSpec.describe Gitlab::Middleware::ReadOnly do
expect(subject).not_to disallow_request
end
+ context 'relative URL is configured' do
+ before do
+ stub_config_setting(relative_url_root: '/gitlab')
+ end
+
+ it 'expects a graphql request to be allowed' do
+ response = request.post("/gitlab/api/graphql")
+
+ expect(response).not_to be_redirect
+ expect(subject).not_to disallow_request
+ end
+ end
+
context 'sidekiq admin requests' do
where(:mounted_at) do
[
diff --git a/spec/lib/gitlab/repository_set_cache_spec.rb b/spec/lib/gitlab/repository_set_cache_spec.rb
index 024aae49b04..07f4d7c462d 100644
--- a/spec/lib/gitlab/repository_set_cache_spec.rb
+++ b/spec/lib/gitlab/repository_set_cache_spec.rb
@@ -93,23 +93,6 @@ RSpec.describe Gitlab::RepositorySetCache, :clean_gitlab_redis_cache do
it { is_expected.to eq(0) }
end
-
- context "unlink isn't supported" do
- before do
- allow_any_instance_of(Redis).to receive(:unlink) { raise ::Redis::CommandError }
- end
-
- it 'still deletes the given key' do
- expect(cache.expire(:foo)).to eq(1)
- expect(cache.read(:foo)).to be_empty
- end
-
- it 'logs the failure' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception)
-
- cache.expire(:foo)
- end
- end
end
describe '#exist?' do
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 018821e6c5e..b4e47ac4cbb 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -51,6 +51,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
Gitlab::SidekiqMiddleware::BatchLoader,
Labkit::Middleware::Sidekiq::Server,
Gitlab::SidekiqMiddleware::InstrumentationLogger,
+ Gitlab::SidekiqVersioning::Middleware,
Gitlab::SidekiqStatus::ServerMiddleware,
Gitlab::SidekiqMiddleware::ServerMetrics,
Gitlab::SidekiqMiddleware::ArgumentsLogger,
@@ -78,6 +79,41 @@ RSpec.describe Gitlab::SidekiqMiddleware do
end
end
+ shared_examples "a server middleware chain for mailer" do
+ let(:worker_class) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
+ let(:job_args) do
+ [
+ {
+ "job_class" => "ActionMailer::MailDeliveryJob",
+ "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e",
+ "provider_job_id" => nil,
+ "queue_name" => "mailers",
+ "priority" => nil,
+ "arguments" => [
+ "Notify",
+ "test_email",
+ "deliver_now",
+ {
+ "args" => [
+ "test@example.com",
+ "subject",
+ "body"
+ ],
+ "_aj_symbol_keys" => ["args"]
+ }
+ ],
+ "executions" => 0,
+ "exception_executions" => {},
+ "locale" => "en",
+ "timezone" => "UTC",
+ "enqueued_at" => "2020-07-27T07:43:31Z"
+ }
+ ]
+ end
+
+ it_behaves_like "a server middleware chain"
+ end
+
context "all optional middlewares off" do
let(:metrics) { false }
let(:arguments_logger) { false }
@@ -91,6 +127,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
end
it_behaves_like "a server middleware chain"
+ it_behaves_like "a server middleware chain for mailer"
end
context "all optional middlewares on" do
@@ -100,6 +137,7 @@ RSpec.describe Gitlab::SidekiqMiddleware do
let(:disabled_sidekiq_middlewares) { [] }
it_behaves_like "a server middleware chain"
+ it_behaves_like "a server middleware chain for mailer"
context "server metrics" do
let(:gitaly_histogram) { double(:gitaly_histogram) }
diff --git a/spec/lib/gitlab/sidekiq_versioning/middleware_spec.rb b/spec/lib/gitlab/sidekiq_versioning/middleware_spec.rb
new file mode 100644
index 00000000000..dc4d1971a98
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_versioning/middleware_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqVersioning::Middleware do
+ let(:worker_class) do
+ Class.new do
+ def self.name
+ 'DummyWorker'
+ end
+
+ include ApplicationWorker
+
+ version 2
+ end
+ end
+
+ describe '#call' do
+ let(:worker) { worker_class.new }
+ let(:job) { { 'version' => 3, 'queue' => queue } }
+ let(:queue) { worker_class.queue }
+
+ def call!(&block)
+ block ||= -> {}
+ subject.call(worker, job, queue, &block)
+ end
+
+ it 'sets worker.job_version' do
+ call!
+
+ expect(worker.job_version).to eq(job['version'])
+ end
+
+ it 'yields' do
+ expect { |b| call!(&b) }.to yield_control
+ end
+
+ context 'when worker is not ApplicationWorker' do
+ let(:worker_class) do
+ ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper
+ end
+
+ it 'does not err' do
+ expect { call! }.not_to raise_error
+ end
+ end
+
+ context 'when sidekiq_versioning is disabled' do
+ before do
+ stub_feature_flags(sidekiq_versioning: false)
+ end
+
+ it 'does not set job_version' do
+ expect(worker).not_to receive(:job_version=)
+
+ call!
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_versioning/worker_spec.rb b/spec/lib/gitlab/sidekiq_versioning/worker_spec.rb
new file mode 100644
index 00000000000..0781c5100fd
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_versioning/worker_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SidekiqVersioning::Worker do
+ let(:worker) do
+ Class.new do
+ def self.name
+ 'DummyWorker'
+ end
+
+ # ApplicationWorker includes Gitlab::SidekiqVersioning::Worker
+ include ApplicationWorker
+
+ version 2
+ end
+ end
+
+ describe '.version' do
+ context 'when called with an argument' do
+ it 'sets the version option' do
+ worker.version 3
+
+ expect(worker.get_sidekiq_options['version']).to eq(3)
+ end
+ end
+
+ context 'when called without an argument' do
+ it 'returns the version option' do
+ worker.sidekiq_options version: 3
+
+ expect(worker.version).to eq(3)
+ end
+ end
+ end
+
+ describe '#job_version' do
+ let(:job) { worker.new }
+
+ context 'when job_version is not set' do
+ it 'returns latest version' do
+ expect(job.job_version).to eq(2)
+ end
+ end
+
+ context 'when job_version is set' do
+ it 'returns the set version' do
+ job.job_version = 0
+
+ expect(job.job_version).to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 2c246bd475b..7371fe5c3f7 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe ProjectPolicy do
resolve_note create_container_image update_container_image destroy_container_image daily_statistics
create_environment update_environment create_deployment update_deployment create_release update_release
create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation
- read_terraform_state
+ read_terraform_state read_pod_logs
]
end
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index b4e83c8caab..2af97c4b984 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -17,49 +17,47 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
- context 'without the need for a license' do
- context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPi package versions' | :success
- 'PUBLIC' | :guest | true | true | 'PyPi package versions' | :success
- 'PUBLIC' | :developer | true | false | 'PyPi package versions' | :success
- 'PUBLIC' | :guest | true | false | 'PyPi package versions' | :success
- 'PUBLIC' | :developer | false | true | 'PyPi package versions' | :success
- 'PUBLIC' | :guest | false | true | 'PyPi package versions' | :success
- 'PUBLIC' | :developer | false | false | 'PyPi package versions' | :success
- 'PUBLIC' | :guest | false | false | 'PyPi package versions' | :success
- 'PUBLIC' | :anonymous | false | true | 'PyPi package versions' | :success
- 'PRIVATE' | :developer | true | true | 'PyPi package versions' | :success
- 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
+ context 'with valid project' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'PyPi package versions' | :success
+ 'PUBLIC' | :guest | true | true | 'PyPi package versions' | :success
+ 'PUBLIC' | :developer | true | false | 'PyPi package versions' | :success
+ 'PUBLIC' | :guest | true | false | 'PyPi package versions' | :success
+ 'PUBLIC' | :developer | false | true | 'PyPi package versions' | :success
+ 'PUBLIC' | :guest | false | true | 'PyPi package versions' | :success
+ 'PUBLIC' | :developer | false | false | 'PyPi package versions' | :success
+ 'PUBLIC' | :guest | false | false | 'PyPi package versions' | :success
+ 'PUBLIC' | :anonymous | false | true | 'PyPi package versions' | :success
+ 'PRIVATE' | :developer | true | true | 'PyPi package versions' | :success
+ 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
+ end
- subject { get api(url), headers: headers }
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
+ subject { get api(url), headers: headers }
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
+ end
- it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'deploy token for package GET requests'
- it_behaves_like 'rejects PyPI access with unknown project id'
- end
+ it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do
@@ -70,48 +68,46 @@ RSpec.describe API::PypiPackages do
subject { post api(url), headers: headers }
- context 'without the need for a license' do
- context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'process PyPi api request' | :success
- 'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process PyPi api request' | :success
- 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ context 'with valid project' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'process PyPi api request' | :success
+ 'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :developer | true | true | 'process PyPi api request' | :success
+ 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
+ end
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
+ let(:headers) { user_headers.merge(workhorse_header) }
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
+ end
- it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'deploy token for package uploads'
- it_behaves_like 'rejects PyPI access with unknown project id'
- end
+ it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'POST /api/v4/projects/:id/packages/pypi' do
@@ -135,61 +131,59 @@ RSpec.describe API::PypiPackages do
)
end
- context 'without the need for a license' do
- context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPi package creation' | :created
- 'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
- 'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
- 'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :developer | true | true | 'process PyPi api request' | :created
- 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
- 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
- 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
-
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
-
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
- end
+ context 'with valid project' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'PyPi package creation' | :created
+ 'PUBLIC' | :guest | true | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :developer | true | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :guest | true | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :developer | false | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :guest | false | true | 'process PyPi api request' | :forbidden
+ 'PUBLIC' | :developer | false | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :guest | false | false | 'process PyPi api request' | :unauthorized
+ 'PUBLIC' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :developer | true | true | 'process PyPi api request' | :created
+ 'PRIVATE' | :guest | true | true | 'process PyPi api request' | :forbidden
+ 'PRIVATE' | :developer | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | true | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :developer | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :guest | false | true | 'process PyPi api request' | :not_found
+ 'PRIVATE' | :developer | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :guest | false | false | 'process PyPi api request' | :unauthorized
+ 'PRIVATE' | :anonymous | false | true | 'process PyPi api request' | :unauthorized
end
- context 'with an invalid package' do
- let(:token) { personal_access_token.token }
- let(:user_headers) { build_basic_auth_header(user.username, token) }
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:user_headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_header) }
before do
- params[:name] = '.$/@!^*'
- project.add_developer(user)
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
- it_behaves_like 'returning response status', :bad_request
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
+ end
- it_behaves_like 'deploy token for package uploads'
+ context 'with an invalid package' do
+ let(:token) { personal_access_token.token }
+ let(:user_headers) { build_basic_auth_header(user.username, token) }
+ let(:headers) { user_headers.merge(workhorse_header) }
+
+ before do
+ params[:name] = '.$/@!^*'
+ project.add_developer(user)
+ end
- it_behaves_like 'rejects PyPI access with unknown project id'
+ it_behaves_like 'returning response status', :bad_request
end
+
+ it_behaves_like 'deploy token for package uploads'
+
+ it_behaves_like 'rejects PyPI access with unknown project id'
end
describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do
@@ -200,60 +194,58 @@ RSpec.describe API::PypiPackages do
subject { get api(url) }
- context 'without the need for a license' do
- context 'with valid project' do
- using RSpec::Parameterized::TableSyntax
-
- where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
- 'PUBLIC' | :developer | true | true | 'PyPi package download' | :success
- 'PUBLIC' | :guest | true | true | 'PyPi package download' | :success
- 'PUBLIC' | :developer | true | false | 'PyPi package download' | :success
- 'PUBLIC' | :guest | true | false | 'PyPi package download' | :success
- 'PUBLIC' | :developer | false | true | 'PyPi package download' | :success
- 'PUBLIC' | :guest | false | true | 'PyPi package download' | :success
- 'PUBLIC' | :developer | false | false | 'PyPi package download' | :success
- 'PUBLIC' | :guest | false | false | 'PyPi package download' | :success
- 'PUBLIC' | :anonymous | false | true | 'PyPi package download' | :success
- 'PRIVATE' | :developer | true | true | 'PyPi package download' | :success
- 'PRIVATE' | :guest | true | true | 'PyPi package download' | :success
- 'PRIVATE' | :developer | true | false | 'PyPi package download' | :success
- 'PRIVATE' | :guest | true | false | 'PyPi package download' | :success
- 'PRIVATE' | :developer | false | true | 'PyPi package download' | :success
- 'PRIVATE' | :guest | false | true | 'PyPi package download' | :success
- 'PRIVATE' | :developer | false | false | 'PyPi package download' | :success
- 'PRIVATE' | :guest | false | false | 'PyPi package download' | :success
- 'PRIVATE' | :anonymous | false | true | 'PyPi package download' | :success
- end
-
- with_them do
- let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
+ context 'with valid project' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
+ 'PUBLIC' | :developer | true | true | 'PyPi package download' | :success
+ 'PUBLIC' | :guest | true | true | 'PyPi package download' | :success
+ 'PUBLIC' | :developer | true | false | 'PyPi package download' | :success
+ 'PUBLIC' | :guest | true | false | 'PyPi package download' | :success
+ 'PUBLIC' | :developer | false | true | 'PyPi package download' | :success
+ 'PUBLIC' | :guest | false | true | 'PyPi package download' | :success
+ 'PUBLIC' | :developer | false | false | 'PyPi package download' | :success
+ 'PUBLIC' | :guest | false | false | 'PyPi package download' | :success
+ 'PUBLIC' | :anonymous | false | true | 'PyPi package download' | :success
+ 'PRIVATE' | :developer | true | true | 'PyPi package download' | :success
+ 'PRIVATE' | :guest | true | true | 'PyPi package download' | :success
+ 'PRIVATE' | :developer | true | false | 'PyPi package download' | :success
+ 'PRIVATE' | :guest | true | false | 'PyPi package download' | :success
+ 'PRIVATE' | :developer | false | true | 'PyPi package download' | :success
+ 'PRIVATE' | :guest | false | true | 'PyPi package download' | :success
+ 'PRIVATE' | :developer | false | false | 'PyPi package download' | :success
+ 'PRIVATE' | :guest | false | false | 'PyPi package download' | :success
+ 'PRIVATE' | :anonymous | false | true | 'PyPi package download' | :success
+ end
- subject { get api(url), headers: headers }
+ with_them do
+ let(:token) { user_token ? personal_access_token.token : 'wrong' }
+ let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
- end
+ subject { get api(url), headers: headers }
- it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
+
+ it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
+ end
- context 'with deploy token headers' do
- let(:headers) { build_basic_auth_header(deploy_token.username, deploy_token.token) }
+ context 'with deploy token headers' do
+ let(:headers) { build_basic_auth_header(deploy_token.username, deploy_token.token) }
- context 'valid token' do
- it_behaves_like 'returning response status', :success
- end
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
- context 'invalid token' do
- let(:headers) { build_basic_auth_header('foo', 'bar') }
+ context 'invalid token' do
+ let(:headers) { build_basic_auth_header('foo', 'bar') }
- it_behaves_like 'returning response status', :success
- end
+ it_behaves_like 'returning response status', :success
end
-
- it_behaves_like 'rejects PyPI access with unknown project id'
end
+
+ it_behaves_like 'rejects PyPI access with unknown project id'
end
end
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index 6232a0d2973..c90f771335e 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -83,9 +83,9 @@ RSpec.describe EnvironmentEntity do
end
context 'pod_logs' do
- context 'with developer access' do
+ context 'with reporter access' do
before do
- project.add_developer(user)
+ project.add_reporter(user)
end
it 'does not expose logs keys' do
@@ -95,9 +95,9 @@ RSpec.describe EnvironmentEntity do
end
end
- context 'with maintainer access' do
+ context 'with developer access' do
before do
- project.add_maintainer(user)
+ project.add_developer(user)
end
it 'exposes logs keys' do
diff --git a/yarn.lock b/yarn.lock
index b1f099a6333..a65304003b2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1385,7 +1385,7 @@
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
-"@vue/test-utils@^1.0.0-beta.30":
+"@vue/test-utils@1.0.0-beta.30":
version "1.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.30.tgz#d5f26d1e2411fdb7fa7fdedb61b4b4ea4194c49d"
integrity sha512-Wyvcha9fNk8+kzTDwb3xWGjPkCPzHSYSwKP6MplrPTG/auhqoad7JqUEceZLc6u7AU4km2pPQ8/m9s0RgCZ0NA==
@@ -12161,7 +12161,7 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
integrity sha512-2j/t+wIbyVMP5NvctQoSUvLkYKoWAAk2QlQiilrM2a6/ulzFgdcLUJfTvs4XQ/3eZhHiBmmEojbjmM4AzZj8JA==
-vue-jest@^4.0.0-beta.2:
+vue-jest@4.0.0-beta.2:
version "4.0.0-beta.2"
resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-4.0.0-beta.2.tgz#f2120ea9d24224aad3a100c2010b0760d47ee6fe"
integrity sha512-SywBIciuIfqsCb8Eb9UQ02s06+NV8Ry8KnbyhAfnvnyFFulIuh7ujtga9eJYq720nCS4Hz4TpVtS4pD1ZbUILQ==