diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb | 18 | ||||
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/config/content/legacy_auto_devops.rb | 18 | ||||
-rw-r--r-- | lib/gitlab/ci/templates/Beta/Auto-DevOps.gitlab-ci.yml | 163 | ||||
-rw-r--r-- | lib/gitlab/dependency_linker.rb | 3 | ||||
-rw-r--r-- | lib/gitlab/dependency_linker/cargo_toml_linker.rb | 46 | ||||
-rw-r--r-- | lib/gitlab/file_detector.rb | 1 | ||||
-rw-r--r-- | lib/sentry/client.rb | 54 | ||||
-rw-r--r-- | lib/sentry/client/issue.rb | 62 |
8 files changed, 309 insertions, 56 deletions
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb b/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb index e9bcc67de9c..54be789988c 100644 --- a/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb +++ b/lib/gitlab/ci/pipeline/chain/config/content/auto_devops.rb @@ -11,7 +11,7 @@ module Gitlab strong_memoize(:content) do next unless project&.auto_devops_enabled? - template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') + template = Gitlab::Template::GitlabCiYmlTemplate.find(template_name) YAML.dump('include' => [{ 'template' => template.full_name }]) end end @@ -19,6 +19,22 @@ module Gitlab def source :auto_devops_source end + + private + + def template_name + if beta_enabled? + 'Beta/Auto-DevOps' + else + 'Auto-DevOps' + end + end + + def beta_enabled? + Feature.enabled?(:auto_devops_beta, project, default_enabled: true) && + # workflow:rules are required by `Beta/Auto-DevOps.gitlab-ci.yml` + Feature.enabled?(:workflow_rules, project, default_enabled: true) + end end end end diff --git a/lib/gitlab/ci/pipeline/chain/config/content/legacy_auto_devops.rb b/lib/gitlab/ci/pipeline/chain/config/content/legacy_auto_devops.rb index c4cef356628..b282886a56f 100644 --- a/lib/gitlab/ci/pipeline/chain/config/content/legacy_auto_devops.rb +++ b/lib/gitlab/ci/pipeline/chain/config/content/legacy_auto_devops.rb @@ -11,7 +11,7 @@ module Gitlab strong_memoize(:content) do next unless project&.auto_devops_enabled? - template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') + template = Gitlab::Template::GitlabCiYmlTemplate.find(template_name) template.content end end @@ -19,6 +19,22 @@ module Gitlab def source :auto_devops_source end + + private + + def template_name + if beta_enabled? + 'Beta/Auto-DevOps' + else + 'Auto-DevOps' + end + end + + def beta_enabled? + Feature.enabled?(:auto_devops_beta, project, default_enabled: true) && + # workflow:rules are required by `Beta/Auto-DevOps.gitlab-ci.yml` + Feature.enabled?(:workflow_rules, project, default_enabled: true) + end end end end diff --git a/lib/gitlab/ci/templates/Beta/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Beta/Auto-DevOps.gitlab-ci.yml new file mode 100644 index 00000000000..2c5035705ac --- /dev/null +++ b/lib/gitlab/ci/templates/Beta/Auto-DevOps.gitlab-ci.yml @@ -0,0 +1,163 @@ +# Auto DevOps - BETA do not use +# This CI/CD configuration provides a standard pipeline for +# * building a Docker image (using a buildpack if necessary), +# * storing the image in the container registry, +# * running tests from a buildpack, +# * running code quality analysis, +# * creating a review app for each topic branch, +# * and continuous deployment to production +# +# Test jobs may be disabled by setting environment variables: +# * test: TEST_DISABLED +# * code_quality: CODE_QUALITY_DISABLED +# * license_management: LICENSE_MANAGEMENT_DISABLED +# * performance: PERFORMANCE_DISABLED +# * sast: SAST_DISABLED +# * dependency_scanning: DEPENDENCY_SCANNING_DISABLED +# * container_scanning: CONTAINER_SCANNING_DISABLED +# * dast: DAST_DISABLED +# * review: REVIEW_DISABLED +# * stop_review: REVIEW_DISABLED +# +# In order to deploy, you must have a Kubernetes cluster configured either +# via a project integration, or via group/project variables. +# KUBE_INGRESS_BASE_DOMAIN must also be set on the cluster settings, +# as a variable at the group or project level, or manually added below. +# +# Continuous deployment to production is enabled by default. +# If you want to deploy to staging first, set STAGING_ENABLED environment variable. +# If you want to enable incremental rollout, either manual or time based, +# set INCREMENTAL_ROLLOUT_MODE environment variable to "manual" or "timed". +# If you want to use canary deployments, set CANARY_ENABLED environment variable. +# +# If Auto DevOps fails to detect the proper buildpack, or if you want to +# specify a custom buildpack, set a project variable `BUILDPACK_URL` to the +# repository URL of the buildpack. +# e.g. BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-ruby.git#v142 +# If you need multiple buildpacks, add a file to your project called +# `.buildpacks` that contains the URLs, one on each line, in order. +# Note: Auto CI does not work with multiple buildpacks yet + +image: alpine:latest + +variables: + # KUBE_INGRESS_BASE_DOMAIN is the application deployment domain and should be set as a variable at the group or project level. + # KUBE_INGRESS_BASE_DOMAIN: domain.example.com + + POSTGRES_USER: user + POSTGRES_PASSWORD: testing-password + POSTGRES_ENABLED: "true" + POSTGRES_DB: $CI_ENVIRONMENT_SLUG + POSTGRES_VERSION: 9.6.2 + + DOCKER_DRIVER: overlay2 + + ROLLOUT_RESOURCE_TYPE: deployment + + DOCKER_TLS_CERTDIR: "" # https://gitlab.com/gitlab-org/gitlab-runner/issues/4501 + +stages: + - build + - test + - deploy # dummy stage to follow the template guidelines + - review + - dast + - staging + - canary + - production + - incremental rollout 10% + - incremental rollout 25% + - incremental rollout 50% + - incremental rollout 100% + - performance + - cleanup + +workflow: + rules: + - if: '$BUILDPACK_URL || $AUTO_DEVOPS_EXPLICITLY_ENABLED == "1"' + + - exists: + - Dockerfile + + # https://github.com/heroku/heroku-buildpack-clojure + - exists: + - project.clj + + # https://github.com/heroku/heroku-buildpack-go + - exists: + - go.mod + - Gopkg.mod + - Godeps/Godeps.json + - vendor/vendor.json + - glide.yaml + - src/**/*.go + + # https://github.com/heroku/heroku-buildpack-gradle + - exists: + - gradlew + - build.gradle + - settings.gradle + + # https://github.com/heroku/heroku-buildpack-java + - exists: + - pom.xml + - pom.atom + - pom.clj + - pom.groovy + - pom.rb + - pom.scala + - pom.yaml + - pom.yml + + # https://github.com/heroku/heroku-buildpack-multi + - exists: + - .buildpacks + + # https://github.com/heroku/heroku-buildpack-nodejs + - exists: + - package.json + + # https://github.com/heroku/heroku-buildpack-php + - exists: + - composer.json + - index.php + + # https://github.com/heroku/heroku-buildpack-play + # TODO: detect script excludes some scala files + - exists: + - '**/conf/application.conf' + + # https://github.com/heroku/heroku-buildpack-python + # TODO: detect script checks that all of these exist, not any + - exists: + - requirements.txt + - setup.py + - Pipfile + + # https://github.com/heroku/heroku-buildpack-ruby + - exists: + - Gemfile + + # https://github.com/heroku/heroku-buildpack-scala + - exists: + - '*.sbt' + - project/*.scala + - .sbt/*.scala + - project/build.properties + + # https://github.com/dokku/buildpack-nginx + - exists: + - .static + +include: + - template: Jobs/Build.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml + - template: Jobs/Test.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Test.gitlab-ci.yml + - template: Jobs/Code-Quality.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml + - template: Jobs/Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml + - template: Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml + - template: Jobs/Browser-Performance-Testing.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml + - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml + - template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml + - template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml + - template: Security/License-Management.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml + - template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index c63d9e5bb71..7af380689d5 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -12,7 +12,8 @@ module Gitlab PodspecJsonLinker, CartfileLinker, GodepsJsonLinker, - RequirementsTxtLinker + RequirementsTxtLinker, + CargoTomlLinker ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/cargo_toml_linker.rb b/lib/gitlab/dependency_linker/cargo_toml_linker.rb new file mode 100644 index 00000000000..57e0a5f4699 --- /dev/null +++ b/lib/gitlab/dependency_linker/cargo_toml_linker.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Gitlab + module DependencyLinker + class CargoTomlLinker < BaseLinker + self.file_type = :cargo_toml + + def link + return highlighted_text unless toml + + super + end + + private + + def link_dependencies + link_dependencies_at("dependencies") + link_dependencies_at("dev-dependencies") + link_dependencies_at("build-dependencies") + end + + def link_dependencies_at(type) + dependencies = toml[type] + return unless dependencies + + dependencies.each do |name, value| + link_toml(name, value, type) do |name| + "https://crates.io/crates/#{name}" + end + end + end + + def link_toml(key, value, type, &url_proc) + if value.is_a? String + link_regex(/^(?<name>#{key})\s*=\s*"#{value}"/, &url_proc) + else + link_regex(/^\[#{type}\.(?<name>#{key})]/, &url_proc) + end + end + + def toml + @toml ||= TomlRB.parse(plain_text) rescue nil + end + end + end +end diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index a386c21983d..234c834a83a 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -25,6 +25,7 @@ module Gitlab route_map: '.gitlab/route-map.yml', # Dependency files + cargo_toml: 'Cargo.toml', cartfile: %r{\ACartfile[^/]*\z}, composer_json: 'composer.json', gemfile: /\A(Gemfile|gems\.rb)\z/, diff --git a/lib/sentry/client.rb b/lib/sentry/client.rb index 3df688a1fda..dd589b6194d 100644 --- a/lib/sentry/client.rb +++ b/lib/sentry/client.rb @@ -3,6 +3,7 @@ module Sentry class Client include Sentry::Client::Projects + include Sentry::Client::Issue Error = Class.new(StandardError) MissingKeysError = Class.new(StandardError) @@ -23,12 +24,6 @@ module Sentry @token = token end - def issue_details(issue_id:) - issue = get_issue(issue_id: issue_id) - - map_to_detailed_error(issue) - end - def issue_latest_event(issue_id:) latest_event = get_issue_latest_event(issue_id: issue_id) @@ -107,10 +102,6 @@ module Sentry }.compact end - def get_issue(issue_id:) - http_get(issue_api_url(issue_id))[:body] - end - def get_issue_latest_event(issue_id:) http_get(issue_latest_event_api_url(issue_id))[:body] end @@ -145,13 +136,6 @@ module Sentry raise Client::Error, message end - def issue_api_url(issue_id) - issue_url = URI(@url) - issue_url.path = "/api/0/issues/#{issue_id}/" - - issue_url - end - def issue_latest_event_api_url(issue_id) latest_event_url = URI(@url) latest_event_url.path = "/api/0/issues/#{issue_id}/events/latest/" @@ -212,42 +196,6 @@ module Sentry stack_trace_entry.dig('stacktrace', 'frames') end - def parse_gitlab_issue(plugin_issues) - return unless plugin_issues - - gitlab_plugin = plugin_issues.detect { |item| item['id'] == 'gitlab' } - return unless gitlab_plugin - - gitlab_plugin.dig('issue', 'url') - end - - def map_to_detailed_error(issue) - Gitlab::ErrorTracking::DetailedError.new( - id: issue.fetch('id'), - first_seen: issue.fetch('firstSeen', nil), - last_seen: issue.fetch('lastSeen', nil), - title: issue.fetch('title', nil), - type: issue.fetch('type', nil), - user_count: issue.fetch('userCount', nil), - count: issue.fetch('count', nil), - message: issue.dig('metadata', 'value'), - culprit: issue.fetch('culprit', nil), - external_url: issue_url(issue.fetch('id')), - external_base_url: project_url, - short_id: issue.fetch('shortId', nil), - status: issue.fetch('status', nil), - frequency: issue.dig('stats', '24h'), - project_id: issue.dig('project', 'id'), - project_name: issue.dig('project', 'name'), - project_slug: issue.dig('project', 'slug'), - gitlab_issue: parse_gitlab_issue(issue.fetch('pluginIssues', nil)), - first_release_last_commit: issue.dig('firstRelease', 'lastCommit'), - last_release_last_commit: issue.dig('lastRelease', 'lastCommit'), - first_release_short_version: issue.dig('firstRelease', 'shortVersion'), - last_release_short_version: issue.dig('lastRelease', 'shortVersion') - ) - end - def map_to_error(issue) Gitlab::ErrorTracking::Error.new( id: issue.fetch('id'), diff --git a/lib/sentry/client/issue.rb b/lib/sentry/client/issue.rb new file mode 100644 index 00000000000..08ed5392a11 --- /dev/null +++ b/lib/sentry/client/issue.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module Sentry + class Client + module Issue + def issue_details(issue_id:) + issue = get_issue(issue_id: issue_id) + + map_to_detailed_error(issue) + end + + private + + def get_issue(issue_id:) + http_get(issue_api_url(issue_id))[:body] + end + + def issue_api_url(issue_id) + issue_url = URI(url) + issue_url.path = "/api/0/issues/#{CGI.escape(issue_id.to_s)}/" + + issue_url + end + + def parse_gitlab_issue(plugin_issues) + return unless plugin_issues + + gitlab_plugin = plugin_issues.detect { |item| item['id'] == 'gitlab' } + return unless gitlab_plugin + + gitlab_plugin.dig('issue', 'url') + end + + def map_to_detailed_error(issue) + Gitlab::ErrorTracking::DetailedError.new( + id: issue.fetch('id'), + first_seen: issue.fetch('firstSeen', nil), + last_seen: issue.fetch('lastSeen', nil), + title: issue.fetch('title', nil), + type: issue.fetch('type', nil), + user_count: issue.fetch('userCount', nil), + count: issue.fetch('count', nil), + message: issue.dig('metadata', 'value'), + culprit: issue.fetch('culprit', nil), + external_url: issue_url(issue.fetch('id')), + external_base_url: project_url, + short_id: issue.fetch('shortId', nil), + status: issue.fetch('status', nil), + frequency: issue.dig('stats', '24h'), + project_id: issue.dig('project', 'id'), + project_name: issue.dig('project', 'name'), + project_slug: issue.dig('project', 'slug'), + gitlab_issue: parse_gitlab_issue(issue.fetch('pluginIssues', nil)), + first_release_last_commit: issue.dig('firstRelease', 'lastCommit'), + last_release_last_commit: issue.dig('lastRelease', 'lastCommit'), + first_release_short_version: issue.dig('firstRelease', 'shortVersion'), + last_release_short_version: issue.dig('lastRelease', 'shortVersion') + ) + end + end + end +end |