Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
59f37a9943
commit
364e69bafd
|
@ -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 #
|
||||
|
|
|
@ -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)
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -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'
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
·
|
||||
= 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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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. |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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' }
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue