Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-07 21:09:59 +00:00
parent 59f37a9943
commit 364e69bafd
40 changed files with 1372 additions and 300 deletions

View File

@ -664,7 +664,8 @@
.shared:rules:update-gitaly-binaries-cache:
rules:
- <<: *if-merge-request-labels-update-caches
- changes: *gitaly-patterns
- <<: *if-default-refs
changes: *gitaly-patterns
######################
# Build images rules #
@ -693,8 +694,10 @@
- <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
- <<: *if-ruby3-branch
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
- <<: *if-default-refs
changes: *ci-build-images-patterns
- <<: *if-default-refs
changes: *code-qa-patterns
#################
# Caching rules #
@ -856,15 +859,20 @@
- <<: *if-merge-request-targeting-stable-branch
- <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *ci-build-images-patterns
- <<: *if-default-refs
changes: *code-qa-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
.frontend:rules:compile-test-assets:
rules:
- <<: *if-merge-request-labels-run-all-rspec
- changes: *code-backstage-qa-patterns
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
.frontend:rules:compile-test-assets-as-if-foss:
rules:
@ -872,14 +880,18 @@
when: never
- <<: *if-merge-request-labels-as-if-foss
- <<: *if-merge-request-labels-run-all-rspec
- changes: *code-backstage-qa-patterns
- changes: *startup-css-patterns
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *startup-css-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
.frontend:rules:default-frontend-jobs:
rules:
- <<: *if-merge-request-labels-run-all-rspec
- changes: *code-backstage-patterns
- <<: *if-default-refs
changes: *code-backstage-patterns
.frontend:rules:default-frontend-jobs-as-if-foss:
rules:
@ -1124,7 +1136,8 @@
###############
.rails:rules:setup-test-env:
rules:
- changes: *setup-test-env-patterns
- <<: *if-default-refs
changes: *setup-test-env-patterns
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:single-db:
@ -1156,7 +1169,8 @@
changes: *db-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *db-patterns
- <<: *if-default-refs
changes: *db-patterns
.rails:rules:ee-and-foss-migration:minimal:
rules:
@ -1189,7 +1203,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
- <<: *if-default-refs
changes: *backend-patterns
.rails:rules:ee-and-foss-unit:minimal:
rules:
@ -1205,7 +1220,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
- <<: *if-default-refs
changes: *backend-patterns
.rails:rules:ee-and-foss-integration:minimal:
rules:
@ -1221,7 +1237,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:system-default-rules", rules]
- changes: *code-backstage-patterns
- <<: *if-default-refs
changes: *code-backstage-patterns
.rails:rules:ee-and-foss-system:minimal:
rules:
@ -1235,11 +1252,13 @@
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *backend-patterns
- changes: *core-backend-patterns
- <<: *if-default-refs
changes: *core-backend-patterns
.rails:rules:code-backstage-qa:
rules:
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:ee-only-migration:
@ -1259,7 +1278,8 @@
changes: *db-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *db-patterns
- <<: *if-default-refs
changes: *db-patterns
.rails:rules:ee-only-migration:minimal:
rules:
@ -1280,7 +1300,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
- <<: *if-default-refs
changes: *backend-patterns
.rails:rules:ee-only-unit:minimal:
rules:
@ -1300,7 +1321,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:ee-and-foss-default-rules", rules]
- changes: *backend-patterns
- <<: *if-default-refs
changes: *backend-patterns
.rails:rules:ee-only-integration:minimal:
rules:
@ -1320,7 +1342,8 @@
- <<: *if-fork-merge-request
when: never
- !reference [".rails:rules:system-default-rules", rules]
- changes: *code-backstage-patterns
- <<: *if-default-refs
changes: *code-backstage-patterns
.rails:rules:ee-only-system:minimal:
rules:
@ -1434,7 +1457,8 @@
.rails:rules:ee-and-foss-db-library-code:
rules:
- changes: *db-library-patterns
- <<: *if-default-refs
changes: *db-library-patterns
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:ee-mr-and-default-branch-only:
@ -1450,8 +1474,10 @@
.rails:rules:detect-tests:
rules:
- <<: *if-merge-request-labels-run-all-rspec
- changes: *code-backstage-qa-patterns
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
.rails:rules:detect-previous-failed-tests:
rules:
@ -1542,7 +1568,8 @@
rules:
- <<: *if-not-ee
when: never
- changes: *code-backstage-patterns
- <<: *if-default-refs
changes: *code-backstage-patterns
.rails:rules:flaky-tests-report:
rules:
@ -1560,38 +1587,51 @@
.static-analysis:rules:static-analysis:
rules:
- changes: *code-backstage-qa-patterns
- changes: *static-analysis-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *static-analysis-patterns
.static-analysis:rules:static-verification-with-database:
rules:
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
.static-analysis:rules:rubocop:
rules:
- changes: *rubocop-patterns
- <<: *if-default-refs
changes: *rubocop-patterns
variables:
RUN_ALL_RUBOCOP: "true"
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
.static-analysis:rules:qa:metadata-lint:
rules:
- changes: *qa-patterns
- changes: [".gitlab/ci/static-analysis.gitlab-ci.yml"]
- <<: *if-default-refs
changes: *qa-patterns
- <<: *if-default-refs
changes: [".gitlab/ci/static-analysis.gitlab-ci.yml"]
.static-analysis:rules:haml-lint:
rules:
- changes: *rubocop-patterns
- changes: *static-analysis-patterns
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *rubocop-patterns
- <<: *if-default-refs
changes: *static-analysis-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
.static-analysis:rules:haml-lint-ee:
rules:
- <<: *if-not-ee
when: never
- changes: *rubocop-patterns
- changes: *static-analysis-patterns
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *rubocop-patterns
- <<: *if-default-refs
changes: *static-analysis-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
.static-analysis:rules:static-analysis-as-if-foss:
rules:
@ -1709,7 +1749,8 @@
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
when: never
- changes:
- <<: *if-default-refs
changes:
- '**/*.rb'
- '**/Gemfile'
@ -1719,7 +1760,8 @@
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
when: never
- changes:
- <<: *if-default-refs
changes:
- '**/*.py'
- '**/*.js'
- '**/*.jsx'
@ -1735,7 +1777,8 @@
when: never
# Scan each commit on master to feed the Vulnerability Reports with detected secrets
- <<: *if-default-branch-refs
- changes: *code-backstage-qa-patterns
- <<: *if-default-refs
changes: *code-backstage-qa-patterns
.reports:rules:gemnasium-dependency_scanning:
rules:
@ -1743,7 +1786,8 @@
when: never
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
- <<: *if-default-branch-refs
- changes: *dependency-patterns
- <<: *if-default-refs
changes: *dependency-patterns
.reports:rules:gemnasium-python-dependency_scanning:
rules:
@ -1751,7 +1795,8 @@
when: never
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
- <<: *if-default-branch-refs
- changes: *python-patterns
- <<: *if-default-refs
changes: *python-patterns
.reports:rules:yarn-audit-dependency_scanning:
rules:
@ -1759,7 +1804,8 @@
when: never
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
- <<: *if-default-branch-refs
- changes: *nodejs-patterns
- <<: *if-default-refs
changes: *nodejs-patterns
.reports:rules:schedule-dast:
rules:
@ -1793,7 +1839,8 @@
rules:
- if: '$LICENSE_MANAGEMENT_DISABLED || $GITLAB_FEATURES !~ /\blicense_scanning\b/'
when: never
- changes: *dependency-patterns
- <<: *if-default-refs
changes: *dependency-patterns
################
# Review rules #
@ -1980,7 +2027,8 @@
- <<: *if-not-ee
when: never
- <<: *if-dot-com-ee-schedule-maintenance
- changes:
- <<: *if-default-refs
changes:
- ".gitlab/ci/setup.gitlab-ci.yml"
- ".gitlab/ci/test-metadata.gitlab-ci.yml"
- "scripts/rspec_helpers.sh"
@ -1990,8 +2038,10 @@
#######################
.test-metadata:rules:retrieve-tests-metadata:
rules:
- changes: *code-backstage-patterns
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *code-backstage-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
- <<: *if-merge-request-labels-run-all-rspec
.test-metadata:rules:update-tests-metadata:
@ -1999,7 +2049,8 @@
- <<: *if-not-ee
when: never
- <<: *if-dot-com-ee-schedule-maintenance
- changes:
- <<: *if-default-refs
changes:
- ".gitlab/ci/test-metadata.gitlab-ci.yml"
- "scripts/rspec_helpers.sh"
@ -2008,7 +2059,8 @@
###################
.workhorse:rules:workhorse:
rules:
- changes: *workhorse-patterns
- <<: *if-default-refs
changes: *workhorse-patterns
###################
# yaml-lint rules #

View File

@ -2,6 +2,12 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 15.5.3 (2022-11-07)
### Fixed (1 change)
- [Fix Opensearch compatibility check](gitlab-org/gitlab@c7094017eb6fae71c0b8441a04f6927ed69025ea) ([merge request](gitlab-org/gitlab!103157)) **GitLab Enterprise Edition**
## 15.5.2 (2022-11-02)
### Security (11 changes)

View File

@ -151,7 +151,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
gem 'gitlab-fog-azure-rm', '~> 1.3.0', require: 'fog/azurerm'
gem 'gitlab-fog-azure-rm', '~> 1.4.0', require: 'fog/azurerm'
# for Google storage
gem 'google-api-client', '~> 0.33'

View File

@ -203,7 +203,7 @@
{"name":"gitlab-chronic","version":"0.10.5","platform":"ruby","checksum":"f80f18dc699b708870a80685243331290bc10cfeedb6b99c92219722f729c875"},
{"name":"gitlab-dangerfiles","version":"3.6.1","platform":"ruby","checksum":"f7b69b093d52acb89095d411cb7b8849f5f3b9e76f8baa4c99b5671f1564865f"},
{"name":"gitlab-experiment","version":"0.7.1","platform":"ruby","checksum":"166dddb3aa83428bcaa93c35684ed01dc4d61f321fd2ae40b020806dc54a7824"},
{"name":"gitlab-fog-azure-rm","version":"1.3.0","platform":"ruby","checksum":"2fef5317d6515f95f803099afa860fe3019ce6e1907bf49f66b5e06468a617b5"},
{"name":"gitlab-fog-azure-rm","version":"1.4.0","platform":"ruby","checksum":"af4163c32b028aa5208814a3f4765a5817d50527e6c61931f766bf18a2e0eb7e"},
{"name":"gitlab-labkit","version":"0.28.0","platform":"ruby","checksum":"a7ebf52336566f7607d280056acd64f390c9991f152fc3d6b1dd966a372d5654"},
{"name":"gitlab-license","version":"2.2.1","platform":"ruby","checksum":"39fcf6be8b2887df8afe01b5dcbae8d08b7c5d937ff56b0fb40484a8c4f02d30"},
{"name":"gitlab-mail_room","version":"0.0.9","platform":"ruby","checksum":"6700374b5c0aa9d9ad4e711aeb677f0b7d415a6d01d3baa699efab25349d851c"},

View File

@ -561,7 +561,7 @@ GEM
gitlab-experiment (0.7.1)
activesupport (>= 3.0)
request_store (>= 1.0)
gitlab-fog-azure-rm (1.3.0)
gitlab-fog-azure-rm (1.4.0)
azure-storage-blob (~> 2.0)
azure-storage-common (~> 2.0)
fog-core (= 2.1.0)
@ -1628,7 +1628,7 @@ DEPENDENCIES
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 3.6.1)
gitlab-experiment (~> 0.7.1)
gitlab-fog-azure-rm (~> 1.3.0)
gitlab-fog-azure-rm (~> 1.4.0)
gitlab-labkit (~> 0.28.0)
gitlab-license (~> 2.2.1)
gitlab-mail_room (~> 0.0.9)

View File

@ -7,6 +7,8 @@ class Explore::GroupsController < Explore::ApplicationController
urgency :low
def index
render_group_tree GroupsFinder.new(current_user).execute
user = Feature.enabled?(:generic_explore_groups, current_user, type: :experiment) ? nil : current_user
render_group_tree GroupsFinder.new(user).execute
end
end

View File

@ -1,46 +0,0 @@
# frozen_string_literal: true
module Clusters
module Applications
class CheckIngressIpAddressService < BaseHelmService
include Gitlab::Utils::StrongMemoize
Error = Class.new(StandardError)
LEASE_TIMEOUT = 15.seconds.to_i
def execute
return if app.external_ip
return if app.external_hostname
return unless try_obtain_lease
app.external_ip = ingress_ip if ingress_ip
app.external_hostname = ingress_hostname if ingress_hostname
app.save! if app.changed?
end
private
def try_obtain_lease
Gitlab::ExclusiveLease
.new("check_ingress_ip_address_service:#{app.id}", timeout: LEASE_TIMEOUT)
.try_obtain
end
def ingress_ip
ingress_service&.ip
end
def ingress_hostname
ingress_service&.hostname
end
def ingress_service
strong_memoize(:ingress_service) do
app.ingress_service.status.loadBalancer.ingress&.first
end
end
end
end
end

View File

@ -213,7 +213,15 @@ class EventCreateService
namespace = project.namespace
if Feature.enabled?(:route_hll_to_snowplow, namespace)
Gitlab::Tracking.event(self.class.to_s, 'action_active_users_project_repo', namespace: namespace, user: current_user, project: project)
Gitlab::Tracking.event(
self.class.to_s,
:push,
label: 'usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo',
namespace: namespace,
user: current_user,
project: project,
context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'action_active_users_project_repo').to_context]
)
end
Users::LastPushEventService.new(current_user)

View File

@ -34,8 +34,8 @@
&middot;
= commit.short_id
- if commit.description? && collapsible
%button.gl-button.btn.btn-default.button-ellipsis-horizontal.btn-sm.gl-ml-2.text-expander.js-toggle-button{ data: { toggle: 'tooltip', container: 'body' }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") } }
= sprite_icon('ellipsis_h', size: 12)
= render Pajamas::ButtonComponent.new(icon: 'ellipsis_h',
button_options: { class: 'button-ellipsis-horizontal text-expander js-toggle-button', data: { toggle: 'tooltip', container: 'body' }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") }})
.committer
- commit_author_link = commit_author_link(commit, avatar: false, size: 24)

View File

@ -1,5 +1,8 @@
# frozen_string_literal: true
# DEPRECATED
#
# To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/366573
class ClusterWaitForIngressIpAddressWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
@ -12,9 +15,5 @@ class ClusterWaitForIngressIpAddressWorker # rubocop:disable Scalability/Idempot
worker_has_external_dependencies!
loggable_arguments 0
def perform(app_name, app_id)
find_application(app_name, app_id) do |app|
Clusters::Applications::CheckIngressIpAddressService.new(app).execute
end
end
def perform(app_name, app_id); end
end

View File

@ -0,0 +1,8 @@
---
name: cube_api_proxy
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96250
rollout_issue_url:
milestone: '15.4'
type: development
group: group::product_analytics
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: generic_explore_groups
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/103019"
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/381564
milestone: '15.6'
type: experiment
group: group::source code
default_enabled: false

View File

@ -0,0 +1,21 @@
- name: "`POST /api/v4/runners` method to register runners" # (required) The name of the feature to be deprecated
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
announcement_date: "2022-11-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/379743 # (required) Link to the deprecation issue in GitLab
body: | # (required) Do not modify this line, instead modify the lines below.
The `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint and method [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. We plan to remove this endpoint
and method in GitLab 16.0, and introduce a new
[GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
end_of_support_milestone: "16.0" # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
end_of_support_date: "2023-05-22" # (optional) The date of the milestone release when support for this feature will end.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner # (optional) This is a link to the current documentation page

View File

@ -15,7 +15,7 @@ There are two tokens to take into account when connecting a runner with GitLab.
| Token | Description |
| ----- | ----------- |
| Registration token | Token used to [register the runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/index.md). |
| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runner API when you manually [register a runner](#register-a-new-runner) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). |
| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runner API when you manually [register a runner](#register-a-new-runner-deprecated) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). |
Here's an example of how the two tokens are used in runner registration:
@ -640,7 +640,12 @@ Example response:
]
```
## Register a new runner
## Register a new runner (deprecated)
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102579) in GitLab 15.6.
WARNING:
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102579) in GitLab 15.6 and is planned for removal in 16.0. This change is a breaking change.
Register a new runner for the instance.

View File

@ -11,7 +11,7 @@ description: 'Next Runner Token Architecture'
GitLab Runner is a core component of GitLab CI/CD that runs
CI/CD jobs in a reliable and concurrent environment. Ever since the beginnings
of the service as a Ruby program, runners are registered in a GitLab instance with
of the service as a Ruby program, runners are registered in a GitLab instance with
a registration token - a randomly generated string of text. The registration token is unique for its given scope
(instance, group, or project). The registration token proves that the party that registers the runner has
administrator access to the instance, group, or project to which the runner is registered.
@ -197,7 +197,7 @@ using PAT tokens for example - such that every runner is associated with an owne
| GitLab Runner | `16.0` | Remove `register` command and support for `POST /runners` endpoint. |
| GitLab Rails app | `16.0` | Remove legacy UI showing registration with a registration token. |
| GitLab Rails app | `16.0` | Create database migrations to remove settings from `application_settings` and `namaspace_settings` tables. |
| GitLab Rails app | `16.0` | Make [`POST /api/v4/runners` endpoint](../../../api/runners.md#register-a-new-runner) permanently return `410 Gone`. A future v5 version of the API would return `404 Not Found`. |
| GitLab Rails app | `16.0` | Make [`POST /api/v4/runners` endpoint](../../../api/runners.md#register-a-new-runner-deprecated) permanently return `410 Gone`. A future v5 version of the API would return `404 Not Found`. |
| GitLab Rails app | `16.0` | Start refusing job requests that don't include a unique ID. |
## Status

View File

@ -4,12 +4,12 @@ group: Tutorials
info: For assistance with this tutorial, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects.
---
# Use GitLab to run an agile iteration
# Use GitLab to run an Agile iteration
To run an agile development iteration in GitLab, you use multiple GitLab features
To run an Agile development iteration in GitLab, you use multiple GitLab features
that work together.
To run an agile iteration from GitLab:
To run an Agile iteration from GitLab:
1. Create a group.
1. Create a project.

View File

@ -45,6 +45,32 @@ sole discretion of GitLab Inc.
<div class="announcement-milestone">
## Announced in 15.6
<div class="deprecation removal-160 breaking-change">
### `POST /api/v4/runners` method to register runners
End of Support: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)<br />
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint and method [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. We plan to remove this endpoint
and method in GitLab 16.0, and introduce a new
[GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
</div>
</div>
<div class="announcement-milestone">
## Announced in 15.5
<div class="deprecation removal-157 breaking-change">

View File

@ -64,6 +64,17 @@ This error occurs when you use an activation code to activate your instance, but
You may have connectivity issues due to the following reasons:
- **You have an offline environment**: Configure your setup to allow connection to GitLab servers. If connection to GitLab servers is not possible, contact your Sales Representative to request a license key. You can also contact [GitLab support](https://about.gitlab.com/support/#contact-support) if you need help finding out your Sales Representative.
- **Firewall settings**: Enable an encrypted HTTPS connection from your GitLab instance to `customers.gitlab.com` (with IP addresses 104.18.26.123 and 104.18.27.123) on port 443.
- **Customers Portal is not operational**: To check for performance or service disruptions, check the Customers Portal [status](https://status.gitlab.com/).
- **You have an offline environment**:
- Configure your setup to allow connection to GitLab servers. If connection to GitLab servers is not possible, contact your Sales Representative to request a license key. You can also contact [GitLab support](https://about.gitlab.com/support/#contact-support) if you need help finding your Sales Representative.
- **Customers Portal is not operational**:
- To check for performance or service disruptions, check the Customers Portal [status](https://status.gitlab.com/).
- **Firewall settings**:
- Check if your GitLab instance has an encrypted connection to `customers.gitlab.com` (with IP addresses 104.18.26.123 and 104.18.27.123) on port 443:
```shell
curl --verbose "telnet://customers.gitlab.com/"
```
- If the curl command returns a failure, either:
- [Configure a proxy](https://docs.gitlab.com/omnibus/settings/environment-variables.html) in `gitlab.rb` to point to your server.
- Contact your network administrator to make changes to the proxy.

View File

@ -359,46 +359,12 @@ The container-scanning analyzer can use different scanners, depending on the val
The following options are available:
| Scanner name | `CS_ANALYZER_IMAGE` |
| ------------ | ------------------- |
| Default ([Trivy](https://github.com/aquasecurity/trivy)) | `registry.gitlab.com/security-products/container-scanning:5` |
| Scanner name | `CS_ANALYZER_IMAGE` |
|----------------------------------------------------------|--------------------------------------------------------------------|
| Default ([Trivy](https://github.com/aquasecurity/trivy)) | `registry.gitlab.com/security-products/container-scanning:5` |
| [Grype](https://github.com/anchore/grype) | `registry.gitlab.com/security-products/container-scanning/grype:5` |
| Trivy | `registry.gitlab.com/security-products/container-scanning/trivy:5` |
If you're migrating from a GitLab 13.x release to a GitLab 14.x release and have customized the
`container_scanning` job or its CI variables, you might need to perform these migration steps in
your CI file:
1. Remove these variables:
- `CS_MAJOR_VERSION`
- `CS_PROJECT`
- `SECURE_ANALYZERS_PREFIX`
1. Review the `CS_ANALYZER_IMAGE` variable. It no longer depends on the variables above and its new
default value is `registry.gitlab.com/security-products/container-scanning:5`. If you have an
offline environment, see
[Running container scanning in an offline environment](#running-container-scanning-in-an-offline-environment).
1. If present, remove the `.cs_common` and `container_scanning_new` configuration sections.
1. If the `container_scanning` section is present, it's safer to create one from scratch based on
the new version of the [`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
Once finished, it should not have any variables that are only applicable to Klar or Clair. For a
complete list of supported variables, see [available variables](#available-cicd-variables).
1. Make any [necessary customizations](#customizing-the-container-scanning-settings)
to the chosen scanner. We recommend that you minimize such customizations, as they might require
changes in future GitLab major releases.
1. Trigger a new run of a pipeline that includes the `container_scanning` job. Inspect the job
output and ensure that the log messages do not mention Clair.
NOTE:
Prior to the GitLab 14.0 release, any variable defined under the scope `container_scanning` is not
considered for scanners other than Clair. In GitLab 14.0 and later, all variables can be defined
either as a global variable or under `container_scanning`.
### Setting the default branch image
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338877) in GitLab 14.5.

View File

@ -208,3 +208,24 @@ kubectl delete jobs -l app.kubernetes.io/managed-by=starboard -n gitlab-agent
```
[We're working on making the cleanup of these jobs more robust.](https://gitlab.com/gitlab-org/gitlab/-/issues/362016)
## Inventory policy prevented actuation (strategy: Apply, status: Empty, policy: MustMatch)
```json
{
"error":"inventory policy prevented actuation (strategy: Apply, status: Empty, policy: MustMatch)",
"group":"networking.k8s.io",
"kind":"Deployment",
"name":"resource-name",
"namespace":"namespace",
"status":"Skipped",
"timestamp":"2022-10-29T15:34:21Z",
"type":"apply"
}
```
This error occurs when the GitLab agent tries to update an object and the object doesn't have the required annotations. To fix this error, you can:
- Add the required annotations manually.
- Delete the object and let the agent recreate it.
- Change your [`inventory_policy`](../../infrastructure/clusters/deploy/inventory_object.md#inventory_policy-options) setting.

View File

@ -556,7 +556,7 @@ this setting. However, disabling the Container Registry disables all Container R
## Troubleshooting the GitLab Container Registry
## Migrating OCI container images to GitLab Container Registry
### Migrating OCI container images to GitLab Container Registry
Migrating built container images to the GitLab registry is not a current feature. However, an [epic](https://gitlab.com/groups/gitlab-org/-/epics/5210) is open to track the work on this feature.

View File

@ -253,3 +253,19 @@ If you must unverify both future and past commits,
- [OpenPGP Best Practices](https://riseup.net/en/security/message-security/openpgp/best-practices)
- [Creating a new GPG key with subkeys](https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/) (advanced)
- [Review existing GPG keys in your instance](../../../admin_area/credentials_inventory.md#review-existing-gpg-keys)
## Troubleshooting
### Fix verification problems with signed commits
Commits can be signed with [X.509 certificates](../x509_signed_commits/index.md)
or a GPG key. The verification process for both methods can fail for multiple reasons:
| Value | Description | Possible Fixes |
|-----------------------------|-------------|----------------|
| `UNVERIFIED` | The commit signature is not valid. | Sign the commit with a valid signature. |
| `SAME_USER_DIFFERENT_EMAIL` | The GPG key used to sign the commit does not contain the committer email, but does contain a different valid email for the committer. | Amend the commit to use an email address that matches the GPG key, or update the GPG key [to include the email address](https://security.stackexchange.com/a/261468). |
| `OTHER_USER` | The signature and GPG key are valid, but the key belongs to a different user than the committer. | Amend the commit to use the correct email address, or amend the commit to use a GPG key associated with your user. |
| `UNVERIFIED_KEY` | The key associated with the GPG signature has no verified email address associated with the committer. | Add and verify the email to your GitLab profile, [update the GPG key to include the email address](https://security.stackexchange.com/a/261468), or amend the commit to use a different committer email address. |
| `UNKNOWN_KEY` | The GPG key associated with the GPG signature for this commit is unknown to GitLab. | [Add the GPG key](#add-a-gpg-key-to-your-account) to your GitLab profile. |
| `MULTIPLE_SIGNATURES` | Multiple GPG or X.509 signatures have been found for the commit. | Amend the commit to use only one GPG or X.509 signature. |

View File

@ -163,6 +163,11 @@ can start signing your tags:
## Troubleshooting
For committers without administrator access, review the list of
[verification problems with signed commits](../gpg_signed_commits/index.md#fix-verification-problems-with-signed-commits)
for possible fixes. The other troubleshooting suggestions on this page require
administrator access.
### Re-verify commits
GitLab stores the status of any checked commits in the database. You can use a

View File

@ -13,13 +13,15 @@ module Gitlab
protected_branches = client.branches(repo).select { |branch| branch.dig(:protection, :enabled) }
protected_branches.each do |protected_branch|
next if already_imported?(protected_branch)
object = client.branch_protection(repo, protected_branch[:name])
next if object.nil? || already_imported?(object)
next if object.nil?
yield object
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
mark_as_imported(object)
mark_as_imported(protected_branch)
end
end

123
lib/sbom/package_url.rb Normal file
View File

@ -0,0 +1,123 @@
# frozen_string_literal: true
# MIT License
#
# Copyright (c) 2021 package-url
# Portions Copyright 2022 Gitlab B.V.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
module Sbom
# A package URL, or _purl_, is a URL string used to
# identify and locate a software package in a mostly universal and uniform way
# across programing languages, package managers, packaging conventions, tools,
# APIs and databases.
#
# A purl is a URL composed of seven components:
#
# ```
# scheme:type/namespace/name@version?qualifiers#subpath
# ```
#
# For example,
# the package URL for this Ruby package at version 0.1.0 is
# `pkg:ruby/mattt/packageurl-ruby@0.1.0`.
#
# More details on the package URL format can be found in the purl specification:
# https://github.com/package-url/purl-spec/blob/0b1559f76b79829e789c4f20e6d832c7314762c5/PURL-SPECIFICATION.rst
class PackageUrl
# Raised when attempting to parse an invalid package URL string.
# @see #parse
InvalidPackageURL = Class.new(ArgumentError)
# The URL scheme, which has a constant value of `"pkg"`.
def scheme
'pkg'
end
# The package type or protocol, such as `"gem"`, `"npm"`, and `"github"`.
attr_reader :type
# A name prefix, specific to the type of package.
# For example, an npm scope, a Docker image owner, or a GitHub user.
attr_reader :namespace
# The name of the package.
attr_reader :name
# The version of the package.
attr_reader :version
# Extra qualifying data for a package, specific to the type of package.
# For example, the operating system or architecture.
attr_reader :qualifiers
# An extra subpath within a package, relative to the package root.
attr_reader :subpath
# Constructs a package URL from its components
# @param type [String] The package type or protocol.
# @param namespace [String] A name prefix, specific to the type of package.
# @param name [String] The name of the package.
# @param version [String] The version of the package.
# @param qualifiers [Hash] Extra qualifying data for a package, specific to the type of package.
# @param subpath [String] An extra subpath within a package, relative to the package root.
def initialize(type:, name:, namespace: nil, version: nil, qualifiers: nil, subpath: nil)
raise ArgumentError, 'type is required' unless type.present?
raise ArgumentError, 'name is required' unless name.present?
@type = type.downcase
@namespace = namespace
@name = name
@version = version
@qualifiers = qualifiers
@subpath = subpath
end
# Creates a new PackageURL from a string.
# @param [String] string The package URL string.
# @raise [InvalidPackageURL] If the string is not a valid package URL.
# @return [PackageURL]
def self.parse(string)
Decoder.new(string).decode!
end
# Returns a hash containing the
# scheme, type, namespace, name, version, qualifiers, and subpath components
# of the package URL.
def to_h
{
scheme: scheme,
type: @type,
namespace: @namespace,
name: @name,
version: @version,
qualifiers: @qualifiers,
subpath: @subpath
}
end
# Returns a string representation of the package URL.
# Package URL representations are created according to the instructions from
# https://github.com/package-url/purl-spec/blob/0b1559f76b79829e789c4f20e6d832c7314762c5/PURL-SPECIFICATION.rst#how-to-build-purl-string-from-its-components.
def to_s
Encoder.new(self).encode
end
end
end

View File

@ -0,0 +1,174 @@
# frozen_string_literal: true
# MIT License
#
# Copyright (c) 2021 package-url
# Portions Copyright 2022 Gitlab B.V.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
module Sbom
class PackageUrl
class Decoder
include StringUtils
def initialize(string)
@string = string
end
def decode!
raise ArgumentError, "expected String but given #{@string.class}" unless @string.is_a?(::String)
decode_subpath!
decode_qualifiers!
decode_scheme!
decode_type!
decode_version!
decode_name!
decode_namespace!
PackageUrl.new(
type: @type,
name: @name,
namespace: @namespace,
version: @version,
qualifiers: @qualifiers,
subpath: @subpath
)
end
private
def decode_subpath!
# Split the purl string once from right on '#'
# Given the string: `scheme:type/namespace/name@version?qualifiers#subpath`
# - The left side is the remainder: `scheme:type/namespace/name@version?qualifiers`
# - The right side will be parsed as the subpath: `subpath`
@subpath, @string = partition(@string, '#', from: :right) do |subpath|
decode_segments(subpath) do |segment|
# Discard segments which are blank, `.`, or `..`
segment.empty? || segment == '.' || segment == '..'
end
end
end
def decode_qualifiers!
# Split the remainder once from right on '?'
# Given string: `scheme:type/namespace/name@version?qualifiers`
# - The left side is the remainder: `scheme:type/namespace/name@version`
# - The right side is the qualifiers string: `qualifiers`
@qualifiers, @string = partition(@string, '?', from: :right) do |qualifiers|
parse_qualifiers(qualifiers)
end
end
def decode_scheme!
# Split the remainder once from left on ':'
# Given the string: `scheme:type/namespace/name@version`
# - The left side lowercased is the scheme: `scheme`
# - The right side is the remainder: `type/namespace/name@version`
@scheme, @string = partition(@string, ':', from: :left)
raise InvalidPackageURL, 'invalid or missing "pkg:" URL scheme' unless @scheme == 'pkg'
end
def decode_type!
# Strip the remainder from leading and trailing '/'
@string = strip(@string, '/')
# Split this once from left on '/'
# Given the string: `type/namespace/name@version`
# - The left side lowercased is the type: `type`
# - The right side is the remainder: `namespace/name@version`
@type, @string = partition(@string, '/', from: :left)
raise InvalidPackageURL, 'invalid or missing package type' if @type.empty?
end
def decode_version!
# Split the remainder once from right on '@'
# Given the string: `namespace/name@version`
# - The left side is the remainder: `namespace/name`
# - The right side is the version: `version`
# - The version must be URI decoded
@version, @string = partition(@string, '@', from: :right) do |version|
URI.decode_www_form_component(version)
end
end
def decode_name!
# Split the remainder once from right on '/'
# Given the string: `namespace/name`
# - The left side is the remainder: `namespace`
# - The right size is the name: `name`
# - The name must be URI decoded
@name, @string = partition(@string, '/', from: :right, require_separator: false) do |name|
URI.decode_www_form_component(name)
end
end
def decode_namespace!
# If there is anything remaining, this is the namespace.
# The namespace may contain multiple segments delimited by `/`.
@namespace = decode_segments(@string, &:empty?) unless @string.empty?
end
def decode_segment(segment)
decoded = URI.decode_www_form_component(segment)
raise InvalidPackageURL, 'slash-separated segments may not contain `/`' if decoded.include?('/')
decoded
end
def decode_segments(string)
string.split('/').filter_map do |segment|
next if block_given? && yield(segment)
decode_segment(segment)
end.join('/')
end
def parse_qualifiers(raw_qualifiers)
# - Split the qualifiers on '&'. Each part is a key=value pair
# - For each pair, split the key=value once from left on '=':
# - The key is the lowercase left side
# - The value is the percent-decoded right side
# - Discard any key/value pairs where the value is empty
# - If the key is checksums,
# split the value on ',' to create a list of checksums
# - This list of key/value is the qualifiers object
raw_qualifiers.split('&').each_with_object({}) do |pair, memo|
key, separator, value = pair.partition('=')
next if separator.empty?
key = key.downcase
value = URI.decode_www_form_component(value)
next if value.empty?
memo[key] = case key
when 'checksums'
value.split(',')
else
value
end
end
end
end
end
end

View File

@ -0,0 +1,137 @@
# frozen_string_literal: true
# MIT License
#
# Copyright (c) 2021 package-url
# Portions Copyright 2022 Gitlab B.V.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
module Sbom
class PackageUrl
class Encoder
include StringUtils
def initialize(package)
@type = package.type
@namespace = package.namespace
@name = package.name
@version = package.version
@qualifiers = package.qualifiers
@subpath = package.subpath
@io = StringIO.new
end
def encode
encode_scheme!
encode_type!
encode_name!
encode_version!
encode_qualifiers!
encode_subpath!
io.string
end
private
attr_reader :io
def encode_scheme!
io.write('pkg:')
end
def encode_type!
# Append the type string to the purl as a lowercase ASCII string
# Append '/' to the purl
io.write(@type)
io.write('/')
end
def encode_name!
# If the namespace is empty:
# - Apply type-specific normalization to the name if needed
# - UTF-8-encode the name if needed in your programming language
# - Append the percent-encoded name to the purl
#
# If the namespace is not empty:
# - Strip the namespace from leading and trailing '/'
# - Split on '/' as segments
# - Apply type-specific normalization to each segment if needed
# - UTF-8-encode each segment if needed in your programming language
# - Percent-encode each segment
# - Join the segments with '/'
# - Append this to the purl
# - Append '/' to the purl
# - Strip the name from leading and trailing '/'
# - Apply type-specific normalization to the name if needed
# - UTF-8-encode the name if needed in your programming language
# - Append the percent-encoded name to the purl
if @namespace.nil?
io.write(URI.encode_www_form_component(@name))
else
io.write(encode_segments(@namespace, &:empty?))
io.write('/')
io.write(URI.encode_www_form_component(strip(@name, '/')))
end
end
def encode_version!
return if @version.nil?
# - Append '@' to the purl
# - UTF-8-encode the version if needed in your programming language
# - Append the percent-encoded version to the purl
io.write('@')
io.write(URI.encode_www_form_component(@version))
end
def encode_qualifiers!
return if @qualifiers.nil? || encoded_qualifiers.empty?
io.write('?')
io.write(encoded_qualifiers)
end
def encoded_qualifiers
@encoded_qualifiers ||= @qualifiers.filter_map do |key, value|
next if value.empty?
next "#{key.downcase}=#{value.join(',')}" if key == 'checksums' && value.is_a?(::Array)
"#{key.downcase}=#{URI.encode_www_form_component(value)}"
end.sort.join('&')
end
def encode_subpath!
return if @subpath.nil? || encoded_subpath.empty?
io.write('#')
io.write(encoded_subpath)
end
def encoded_subpath
@encoded_subpath ||= encode_segments(@subpath) do |segment|
# Discard segments which are blank, `.`, or `..`
segment.empty? || segment == '.' || segment == '..'
end
end
end
end
end

View File

@ -0,0 +1,75 @@
# frozen_string_literal: true
# MIT License
#
# Copyright (c) 2021 package-url
# Portions Copyright 2022 Gitlab B.V.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
module Sbom
class PackageUrl
module StringUtils
private
def strip(string, char)
string.delete_prefix(char).delete_suffix(char)
end
def split_segments(string)
strip(string, '/').split('/')
end
def encode_segments(string)
return '' if string.nil?
split_segments(string).map do |segment|
next if block_given? && yield(segment)
URI.encode_www_form_component(segment)
end.join('/')
end
# Partition the given string on the separator.
# The side being partitioned from is returned as the value,
# with the opposing side being returned as the remainder.
#
# If a block is given, then the (value, remainder) are given
# to the block, and the return value of the block is used as the value.
#
# If `require_separator` is true, then a nil value will be returned
# if the separator is not present.
def partition(string, sep, from: :left, require_separator: true)
value, separator, remainder = if from == :left
left, separator, right = string.partition(sep)
[left, separator, right]
else
left, separator, right = string.rpartition(sep)
[right, separator, left]
end
return [nil, value] if separator.empty? && require_separator
value = yield(value, remainder) if block_given?
[value, remainder]
end
end
end
end

View File

@ -16,7 +16,7 @@ gem 'rspec-retry', '~> 0.6.2', require: 'rspec/retry'
gem 'rspec_junit_formatter', '~> 0.6.0'
gem 'faker', '~> 2.23'
gem 'knapsack', '~> 4.0'
gem 'parallel_tests', '~> 3.13'
gem 'parallel_tests', '~> 4.0'
gem 'rotp', '~> 6.2.0'
gem 'timecop', '~> 0.9.5'
gem 'parallel', '~> 1.22', '>= 1.22.1'

View File

@ -187,7 +187,7 @@ GEM
oj (3.13.21)
os (1.1.4)
parallel (1.22.1)
parallel_tests (3.13.0)
parallel_tests (4.0.0)
parallel
parser (3.1.2.1)
ast (~> 2.4.1)
@ -318,7 +318,7 @@ DEPENDENCIES
nokogiri (~> 1.13, >= 1.13.9)
octokit (~> 6.0.0)
parallel (~> 1.22, >= 1.22.1)
parallel_tests (~> 3.13)
parallel_tests (~> 4.0)
pry-byebug (~> 3.10.1)
rainbow (~> 3.1.1)
rake (~> 13, >= 13.0.6)

View File

@ -0,0 +1,142 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Verify', :runner do
describe 'Pipeline with raw variables in YAML', product_group: :pipeline_authoring, feature_flag: {
name: 'ci_raw_variables_in_yaml_config',
scope: :project
} do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
let(:pipeline_job_name) { 'rspec' }
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-with-raw-variable-pipeline'
end
end
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.project = project
runner.name = executor
runner.tags = [executor]
end
end
let(:commit_ci_file) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
commit.add_files(
[
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
variables:
VAR7:
value: "value 7 $CI_PIPELINE_ID"
expand: false
VAR8:
value: "value 8 $CI_PIPELINE_ID"
expand: false
#{pipeline_job_name}:
tags:
- #{executor}
script:
- echo "VAR1 is $VAR1"
- echo "VAR2 is $VAR2"
- echo "VAR3 is $VAR3"
- echo "VAR4 is $VAR4"
- echo "VAR5 is $VAR5"
- echo "VAR6 is $VAR6"
- echo "VAR7 is $VAR7"
- echo "VAR8 is $VAR8"
variables:
VAR1: "JOBID-$CI_JOB_ID"
VAR2: "PIPELINEID-$CI_PIPELINE_ID and $VAR1"
VAR3:
value: "PIPELINEID-$CI_PIPELINE_ID and $VAR1"
expand: false
VAR4:
value: "JOBID-$CI_JOB_ID"
expand: false
VAR5: "PIPELINEID-$CI_PIPELINE_ID and $VAR4"
VAR6:
value: "PIPELINEID-$CI_PIPELINE_ID and $VAR4"
expand: false
VAR7: "overridden value 7 $CI_PIPELINE_ID"
YAML
}
]
)
end
end
let(:pipeline_id) { project.pipelines.first[:id] }
let(:job_id) { project.job_by_name(pipeline_job_name)[:id] }
def before_do
# TODO: Switch to use `let!` and remove this line when removing FF
commit_ci_file
Flow::Login.sign_in
project.visit!
Flow::Pipeline.visit_latest_pipeline(status: 'passed')
Page::Project::Pipeline::Show.perform do |show|
show.click_job(pipeline_job_name)
end
end
after do
runner&.remove_via_api!
end
context 'when FF is on', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/381487' do
before do
Runtime::Feature.enable(:ci_raw_variables_in_yaml_config, project: project)
sleep 60
before_do
end
it 'expands variables according to expand: true/false', :aggregate_failures do
Page::Project::Job::Show.perform do |show|
expect(show.output).to have_content("VAR1 is JOBID-#{job_id}")
expect(show.output).to have_content("VAR2 is PIPELINEID-#{pipeline_id} and JOBID-#{job_id}")
expect(show.output).to have_content("VAR3 is PIPELINEID-$CI_PIPELINE_ID and $VAR1")
expect(show.output).to have_content("VAR4 is JOBID-$CI_JOB_ID")
expect(show.output).to have_content("VAR5 is PIPELINEID-#{pipeline_id} and JOBID-$CI_JOB_ID")
expect(show.output).to have_content("VAR6 is PIPELINEID-$CI_PIPELINE_ID and $VAR4")
expect(show.output).to have_content("VAR7 is overridden value 7 #{pipeline_id}")
expect(show.output).to have_content("VAR8 is value 8 $CI_PIPELINE_ID")
end
end
end
# TODO: Remove this context when FF :ci_raw_variables_in_yaml_config is removed
# Also archive testcase and close related issue
context 'when FF is off', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/381486' do
before do
Runtime::Feature.disable(:ci_raw_variables_in_yaml_config, project: project)
sleep 60
before_do
end
it 'expands all variables', :aggregate_failures do
Page::Project::Job::Show.perform do |show|
expect(show.output).to have_content("VAR1 is JOBID-#{job_id}")
expect(show.output).to have_content("VAR2 is PIPELINEID-#{pipeline_id} and JOBID-#{job_id}")
expect(show.output).to have_content("VAR3 is PIPELINEID-#{pipeline_id} and JOBID-#{job_id}")
expect(show.output).to have_content("VAR4 is JOBID-#{job_id}")
expect(show.output).to have_content("VAR5 is PIPELINEID-#{pipeline_id} and JOBID-#{job_id}")
expect(show.output).to have_content("VAR6 is PIPELINEID-#{pipeline_id} and JOBID-#{job_id}")
expect(show.output).to have_content("VAR7 is overridden value 7 #{pipeline_id}")
expect(show.output).to have_content("VAR8 is value 8 #{pipeline_id}")
end
end
end
end
end
end

View File

@ -9,31 +9,43 @@ RSpec.describe Explore::GroupsController do
sign_in(user)
end
it 'renders group trees' do
expect(described_class).to include(GroupTree)
end
it 'includes public projects' do
member_of_group = create(:group)
member_of_group.add_developer(user)
public_group = create(:group, :public)
get :index
expect(assigns(:groups)).to contain_exactly(member_of_group, public_group)
end
context 'restricted visibility level is public' do
before do
sign_out(user)
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
shared_examples 'explore groups' do
it 'renders group trees' do
expect(described_class).to include(GroupTree)
end
it 'redirects to login page' do
it 'includes public projects' do
member_of_group = create(:group)
member_of_group.add_developer(user)
public_group = create(:group, :public)
get :index
expect(response).to redirect_to new_user_session_path
expect(assigns(:groups)).to contain_exactly(member_of_group, public_group)
end
context 'restricted visibility level is public' do
before do
sign_out(user)
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
end
it 'redirects to login page' do
get :index
expect(response).to redirect_to new_user_session_path
end
end
end
it_behaves_like 'explore groups'
context 'generic_explore_groups flag is disabled' do
before do
stub_feature_flags(generic_explore_groups: false)
end
it_behaves_like 'explore groups'
end
end

View File

@ -164,6 +164,7 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter do
let(:branch_struct) { Struct.new(:protection, :name, :url, keyword_init: true) }
let(:protection_struct) { Struct.new(:enabled, keyword_init: true) }
let(:protected_branch) { branch_struct.new(name: 'main', protection: protection_struct.new(enabled: true)) }
let(:second_protected_branch) { branch_struct.new(name: 'fix', protection: protection_struct.new(enabled: true)) }
let(:unprotected_branch) { branch_struct.new(name: 'staging', protection: protection_struct.new(enabled: false)) }
# when user has no admin rights on repo
let(:unknown_protection_branch) { branch_struct.new(name: 'development', protection: nil) }
@ -172,9 +173,9 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter do
before do
allow(client).to receive(:branches).with(project.import_source)
.and_return([protected_branch, unprotected_branch, unknown_protection_branch])
.and_return([protected_branch, second_protected_branch, unprotected_branch, unknown_protection_branch])
allow(client).to receive(:branch_protection)
.with(project.import_source, protected_branch.name).once
.with(project.import_source, anything)
.and_return(github_protection_rule)
allow(Gitlab::GithubImport::ObjectCounter).to receive(:increment)
.with(project, :protected_branch, :fetched)
@ -184,12 +185,13 @@ RSpec.describe Gitlab::GithubImport::Importer::ProtectedBranchesImporter do
subject.each_object_to_import do |object|
expect(object).to eq github_protection_rule
end
expect(Gitlab::GithubImport::ObjectCounter).to have_received(:increment).once
expect(Gitlab::GithubImport::ObjectCounter).to have_received(:increment).twice
end
context 'when protected branch is already processed' do
it "doesn't process this branch" do
subject.mark_as_imported(protected_branch)
subject.mark_as_imported(second_protected_branch)
subject.each_object_to_import {}
expect(Gitlab::GithubImport::ObjectCounter).not_to have_received(:increment)

View File

@ -0,0 +1,119 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rspec-parameterized'
require_relative '../../../support/shared_contexts/lib/sbom/package_url_shared_contexts'
RSpec.describe Sbom::PackageUrl::Decoder do
describe '#decode' do
subject(:decode) { described_class.new(url).decode! }
include_context 'with purl matrix'
with_them do
it do
is_expected.to have_attributes(
type: type,
namespace: namespace,
name: name,
version: version,
qualifiers: qualifiers,
subpath: subpath
)
end
end
context 'when no argument is passed' do
let(:url) { nil }
it 'raises an error' do
expect { decode }.to raise_error(ArgumentError)
end
end
context 'when an invalid package URL string is passed' do
let(:url) { 'invalid' }
it 'raises an error' do
expect { decode }.to raise_error(Sbom::PackageUrl::InvalidPackageURL)
end
end
context 'when namespace or subpath contains an encoded slash' do
where(:url) do
[
'pkg:golang/google.org/golang/genproto#googleapis%2fapi%2fannotations',
'pkg:golang/google.org%2fgolang/genproto#googleapis/api/annotations'
]
end
with_them do
it { expect { decode }.to raise_error(Sbom::PackageUrl::InvalidPackageURL) }
end
end
context 'when name contains an encoded slash' do
let(:url) { 'pkg:golang/google.org/golang%2fgenproto#googleapis/api/annotations' }
it do
is_expected.to have_attributes(
type: 'golang',
namespace: 'google.org',
name: 'golang/genproto',
version: nil,
qualifiers: nil,
subpath: 'googleapis/api/annotations'
)
end
end
context 'with URL encoded segments' do
let(:url) do
'pkg:golang/namespace%21/google.golang.org%20genproto@version%21?k=v%21#googleapis%20api%20annotations'
end
it 'decodes them' do
is_expected.to have_attributes(
type: 'golang',
namespace: 'namespace!',
name: 'google.golang.org genproto',
version: 'version!',
qualifiers: { 'k' => 'v!' },
subpath: 'googleapis api annotations'
)
end
end
context 'when segments contain empty values' do
let(:url) { 'pkg:golang/google.golang.org//.././genproto#googleapis/..//./api/annotations' }
it 'removes them from the segments' do
is_expected.to have_attributes(
type: 'golang',
namespace: 'google.golang.org/../.', # . and .. are allowed in the namespace, but not the subpath
name: 'genproto',
version: nil,
qualifiers: nil,
subpath: 'googleapis/api/annotations'
)
end
end
context 'when qualifiers have no value' do
let(:url) { 'pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25&foo=&bar=' }
it 'they are ignored' do
is_expected.to have_attributes(
type: 'rpm',
namespace: 'fedora',
name: 'curl',
version: '7.50.3-1.fc25',
qualifiers: { 'arch' => 'i386',
'distro' => 'fedora-25' },
subpath: nil
)
end
end
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rspec-parameterized'
require_relative '../../../support/shared_contexts/lib/sbom/package_url_shared_contexts'
RSpec.describe Sbom::PackageUrl::Encoder do
describe '#encode' do
let(:package) do
::Sbom::PackageUrl.new(
type: type,
namespace: namespace,
name: name,
version: version,
qualifiers: qualifiers,
subpath: subpath
)
end
subject(:encode) { described_class.new(package).encode }
include_context 'with purl matrix'
with_them do
it { is_expected.to eq(url) }
end
end
end

View File

@ -0,0 +1,144 @@
# frozen_string_literal: true
# MIT License
#
# Copyright (c) 2021 package-url
# Portions Copyright 2022 Gitlab B.V.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
require 'fast_spec_helper'
require 'rspec-parameterized'
require_relative '../../support/helpers/next_instance_of'
require_relative '../../support/shared_contexts/lib/sbom/package_url_shared_contexts'
RSpec.describe Sbom::PackageUrl do
include NextInstanceOf
let(:args) do
{
type: 'example',
namespace: 'test',
name: 'test',
version: '1.0.0',
qualifiers: { 'arch' => 'x86_64' },
subpath: 'path/to/package'
}
end
describe '#initialize' do
subject { described_class.new(**args) }
context 'with well-formed arguments' do
it { is_expected.to have_attributes(**args) }
end
context 'when no arguments are given' do
it { expect { described_class.new }.to raise_error(ArgumentError) }
end
context 'when required parameters are missing' do
where(:param) { %i[type name] }
before do
args[param] = nil
end
with_them do
it { expect { subject }.to raise_error(ArgumentError) }
end
end
describe 'normalization' do
it 'downcases provided type component' do
purl = described_class.new(type: 'EXAMPLE', name: 'test')
expect(purl.type).to eq('example')
expect(purl.name).to eq('test')
end
it 'does not down provided name component' do
purl = described_class.new(type: 'example', name: 'TEST')
expect(purl.type).to eq('example')
expect(purl.name).to eq('TEST')
end
end
end
describe '#parse' do
let(:url) { 'pkg:gem/rails@6.1.6.1' }
subject(:parse) { described_class.parse(url) }
it 'delegates parsing to the decoder' do
expect_next_instance_of(described_class::Decoder, url) do |decoder|
expect(decoder).to receive(:decode!)
end
parse
end
end
describe '#to_h' do
let(:purl) do
described_class.new(
type: type,
namespace: namespace,
name: name,
version: version,
qualifiers: qualifiers,
subpath: subpath
)
end
subject(:to_h) { purl.to_h }
include_context 'with purl matrix'
with_them do
it do
is_expected.to eq(
{
scheme: 'pkg',
type: type,
namespace: namespace,
name: name,
version: version,
qualifiers: qualifiers,
subpath: subpath
}
)
end
end
end
describe '#to_s' do
let(:package) { described_class.new(**args) }
it 'delegates to_s to the encoder' do
expect_next_instance_of(described_class::Encoder, package) do |encoder|
expect(encoder).to receive(:encode)
end
package.to_s
end
end
end

View File

@ -1,44 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Clusters::Applications::CheckIngressIpAddressService do
include ExclusiveLeaseHelpers
let(:application) { create(:clusters_applications_ingress, :installed) }
let(:service) { described_class.new(application) }
let(:kubeclient) { double(::Kubeclient::Client, get_service: kube_service) }
let(:lease_key) { "check_ingress_ip_address_service:#{application.id}" }
let(:ingress) do
[
{
ip: '111.222.111.222',
hostname: 'localhost.localdomain'
}
]
end
let(:kube_service) do
::Kubeclient::Resource.new(
{
status: {
loadBalancer: {
ingress: ingress
}
}
}
)
end
subject { service.execute }
before do
stub_exclusive_lease(lease_key, timeout: 15.seconds.to_i)
allow(application.cluster).to receive(:kubeclient).and_return(kubeclient)
end
include_examples 'check ingress ip executions', :clusters_applications_ingress
include_examples 'check ingress ip executions', :clusters_applications_knative
end

View File

@ -20,33 +20,6 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
end
shared_examples 'Snowplow event' do
let(:label) { nil }
it 'is not emitted if FF is disabled' do
stub_feature_flags(feature_flag_name => false)
subject
expect_no_snowplow_event
end
it 'is emitted' do
params = {
category: category,
action: action,
namespace: namespace,
user: user,
project: project,
label: label
}.compact
subject
expect_snowplow_event(**params)
end
end
describe 'Issues' do
describe '#open_issue' do
let(:issue) { create(:issue) }
@ -95,7 +68,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking' do
let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
let(:label) { 'merge_requests_users' }
let(:action) { 'create' }
@ -121,7 +94,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking' do
let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
let(:label) { 'merge_requests_users' }
let(:action) { 'close' }
@ -147,7 +120,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking' do
let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
let(:label) { 'merge_requests_users' }
let(:action) { 'merge' }
@ -330,11 +303,16 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
let(:category) { described_class.to_s }
let(:action) { 'action_active_users_project_repo' }
let(:action) { :push }
let(:namespace) { project.namespace }
let(:feature_flag_name) { :route_hll_to_snowplow }
let(:label) { 'usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo' }
let(:context) do
[Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll,
event: 'action_active_users_project_repo').to_context]
end
end
end
@ -355,11 +333,16 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
let(:category) { described_class.to_s }
let(:action) { 'action_active_users_project_repo' }
let(:action) { :push }
let(:namespace) { project.namespace }
let(:feature_flag_name) { :route_hll_to_snowplow }
let(:label) { 'usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo' }
let(:context) do
[Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll,
event: 'action_active_users_project_repo').to_context]
end
end
end
@ -495,7 +478,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
stub_feature_flags(route_hll_to_snowplow_phase2: false)
end
it 'doesnt emit snowwplow events', :snowplow do
it 'doesnt emit snowplow events', :snowplow do
subject
expect_no_snowplow_event
@ -522,7 +505,7 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
let(:note) { create(:diff_note_on_merge_request) }
end
it_behaves_like 'Snowplow event' do
it_behaves_like 'Snowplow event tracking' do
let(:note) { create(:diff_note_on_merge_request) }
let(:category) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION.to_s }
let(:label) { 'merge_requests_users' }

View File

@ -0,0 +1,98 @@
# frozen_string_literal: true
RSpec.shared_context 'with purl matrix' do
where do
{
'valid RubyGems package URL' => {
url: 'pkg:gem/ruby-advisory-db-check@0.12.4',
type: 'gem',
namespace: nil,
name: 'ruby-advisory-db-check',
version: '0.12.4',
qualifiers: nil,
subpath: nil
},
'valid BitBucket package URL' => {
url: 'pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c',
type: 'bitbucket',
namespace: 'birkenfeld',
name: 'pygments-main',
version: '244fd47e07d1014f0aed9c',
qualifiers: nil,
subpath: nil
},
'valid GitHub package URL' => {
url: 'pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c',
type: 'github',
namespace: 'package-url',
name: 'purl-spec',
version: '244fd47e07d1004f0aed9c',
qualifiers: nil,
subpath: nil
},
'valid Go module URL' => {
url: 'pkg:golang/google.golang.org/genproto#googleapis/api/annotations',
type: 'golang',
namespace: 'google.golang.org',
name: 'genproto',
version: nil,
qualifiers: nil,
subpath: 'googleapis/api/annotations'
},
'valid Maven package URL' => {
url: 'pkg:maven/org.apache.commons/io@1.3.4',
type: 'maven',
namespace: 'org.apache.commons',
name: 'io',
version: '1.3.4',
qualifiers: nil,
subpath: nil
},
'valid NPM package URL' => {
url: 'pkg:npm/foobar@12.3.1',
type: 'npm',
namespace: nil,
name: 'foobar',
version: '12.3.1',
qualifiers: nil,
subpath: nil
},
'valid NuGet package URL' => {
url: 'pkg:nuget/EnterpriseLibrary.Common@6.0.1304',
type: 'nuget',
namespace: nil,
name: 'EnterpriseLibrary.Common',
version: '6.0.1304',
qualifiers: nil,
subpath: nil
},
'valid PyPI package URL' => {
url: 'pkg:pypi/django@1.11.1',
type: 'pypi',
namespace: nil,
name: 'django',
version: '1.11.1',
qualifiers: nil,
subpath: nil
},
'valid RPM package URL' => {
url: 'pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25',
type: 'rpm',
namespace: 'fedora',
name: 'curl',
version: '7.50.3-1.fc25',
qualifiers: { 'arch' => 'i386', 'distro' => 'fedora-25' },
subpath: nil
},
'package URL with checksums' => {
url: 'pkg:rpm/name?checksums=a,b,c',
type: 'rpm',
namespace: nil,
name: 'name',
version: nil,
qualifiers: { 'checksums' => %w[a b c] },
subpath: nil
}
}
end
end

View File

@ -1,32 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ClusterWaitForIngressIpAddressWorker do
describe '#perform' do
let(:service) { instance_double(Clusters::Applications::CheckIngressIpAddressService, execute: true) }
let(:application) { instance_double(Clusters::Applications::Ingress) }
let(:worker) { described_class.new }
before do
allow(worker)
.to receive(:find_application)
.with('ingress', 117)
.and_yield(application)
allow(Clusters::Applications::CheckIngressIpAddressService)
.to receive(:new)
.with(application)
.and_return(service)
allow(described_class)
.to receive(:perform_in)
end
it 'finds the application and calls CheckIngressIpAddressService#execute' do
worker.perform('ingress', 117)
expect(service).to have_received(:execute)
end
end
end