Commit a6d3e124 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'invalid-environment-not-being-created-should-be-surfaced-to-user-v2' into 'master'

Surface the error for invalid environment creation

See merge request gitlab-org/gitlab!71367
parents 5fef4d01 8c4f6e12
......@@ -27,6 +27,7 @@ module Enums
no_matching_runner: 18, # not used anymore, but cannot be deleted because of old data
trace_size_exceeded: 19,
builds_disabled: 20,
environment_creation_failure: 21,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
......
......@@ -28,7 +28,12 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
ci_quota_exceeded: 'No more CI minutes available',
no_matching_runner: 'No matching runner available',
trace_size_exceeded: 'The job log size limit was reached',
builds_disabled: 'The CI/CD is disabled for this project'
builds_disabled: 'The CI/CD is disabled for this project',
environment_creation_failure: 'This job could not be executed because it would create an environment with an invalid parameter.'
}.freeze
TROUBLESHOOTING_DOC = {
environment_creation_failure: { path: 'ci/environments/index', anchor: 'a-deployment-job-failed-with-this-job-could-not-be-executed-because-it-would-create-an-environment-with-an-invalid-parameter-error' }
}.freeze
private_constant :CALLOUT_FAILURE_MESSAGES
......@@ -40,7 +45,19 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
end
def callout_failure_message
self.class.callout_failure_messages.fetch(failure_reason.to_sym)
message = self.class.callout_failure_messages.fetch(failure_reason.to_sym)
if doc = TROUBLESHOOTING_DOC[failure_reason.to_sym]
message += " #{help_page_link(doc[:path], doc[:anchor])}"
end
message
end
private
def help_page_link(path, anchor)
ActionController::Base.helpers.link_to('How do I fix it?', help_page_path(path, anchor: anchor))
end
end
......
---
name: surface_environment_creation_failure
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340169
milestone: '14.4'
type: development
group: group::release
default_enabled: false
---
name: surface_environment_creation_failure_override
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340169
milestone: '14.4'
type: development
group: group::release
default_enabled: false
......@@ -816,3 +816,41 @@ To ensure the `action: stop` can always run when needed, you can:
action: stop
when: manual
```
### A deployment job failed with "This job could not be executed because it would create an environment with an invalid parameter" error
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21182) in GitLab 14.4.
FLAG:
On self-managed GitLab, by default this bug fix is not available. To make it available per project or for your entire instance, ask an administrator to [enable the `surface_environment_creation_failure` flag](../../administration/feature_flags.md). On GitLab.com, this bug fix is not available, but will be rolled out shortly.
If your project is configured to [create a dynamic environment](#create-a-dynamic-environment),
such as a [Review App](../review_apps/index.md), you might encounter this error
because the dynamically generated parameter is invalid for the system.
For example, if you have the following in your `.gitlab-ci.yml`:
```yaml
review:
script: deploy review app
environment: review/$CI_COMMIT_REF_NAME
```
When you create a new merge request with a branch name `bug-fix!`,
the `review` job tries to create an environment with `review/bug-fix!`.
However, the `!` is an invalid character for environments, so the
deployment job fails since it was about to run without an environment.
To fix this, you can:
- Re-create your feature branch without the invalid characters,
such as `bug-fix`.
- Replace the `CI_COMMIT_REF_NAME`
[predefined variable](../variables/predefined_variables.md) with
`CI_COMMIT_REF_SLUG` which strips any invalid characters:
```yaml
review:
script: deploy review app
environment: review/$CI_COMMIT_REF_SLUG
```
......@@ -106,10 +106,15 @@ module Gitlab
environment = Seed::Environment.new(build).to_resource
unless environment.persisted?
if Feature.enabled?(:surface_environment_creation_failure, build.project, default_enabled: :yaml) &&
Feature.disabled?(:surface_environment_creation_failure_override, build.project)
return { status: :failed, failure_reason: :environment_creation_failure }
end
# If there is a validation error on environment creation, such as
# the name contains invalid character, the build falls back to a
# non-environment job.
unless environment.persisted?
Gitlab::ErrorTracking.track_exception(
EnvironmentCreationFailure.new,
project_id: build.project_id,
......
......@@ -33,7 +33,8 @@ module Gitlab
ci_quota_exceeded: 'no more CI minutes available',
no_matching_runner: 'no matching runner available',
trace_size_exceeded: 'log size limit exceeded',
builds_disabled: 'project builds are disabled'
builds_disabled: 'project builds are disabled',
environment_creation_failure: 'environment creation failure'
}.freeze
private_constant :REASONS
......
......@@ -440,6 +440,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
context 'when the environment name is invalid' do
let(:attributes) { { name: 'deploy', ref: 'master', environment: '!!!' } }
it 'fails the job with a failure reason and does not create an environment' do
expect(subject).to be_failed
expect(subject).to be_environment_creation_failure
expect(subject.metadata.expanded_environment_name).to be_nil
expect(Environment.exists?(name: expected_environment_name)).to eq(false)
end
context 'when surface_environment_creation_failure feature flag is disabled' do
before do
stub_feature_flags(surface_environment_creation_failure: false)
end
it_behaves_like 'non-deployment job'
it_behaves_like 'ensures environment inexistence'
......@@ -454,6 +466,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
end
end
end
context 'when job starts a review app' do
let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
......
......@@ -15,6 +15,25 @@ RSpec.describe CommitStatusPresenter do
expect(described_class.superclass).to eq(Gitlab::View::Presenter::Delegated)
end
describe '#callout_failure_message' do
subject { presenter.callout_failure_message }
context 'when troubleshooting doc is available' do
let(:failure_reason) { :environment_creation_failure }
before do
build.failure_reason = failure_reason
end
it 'appends the troubleshooting link' do
doc = described_class::TROUBLESHOOTING_DOC[failure_reason]
expect(subject).to eq("#{described_class.callout_failure_messages[failure_reason]} " \
"<a href=\"#{presenter.help_page_path(doc[:path], anchor: doc[:anchor])}\">How do I fix it?</a>")
end
end
end
describe 'covers all failure reasons' do
let(:message) { presenter.callout_failure_message }
......
......@@ -315,6 +315,10 @@ RSpec.configure do |config|
# For more information check https://gitlab.com/gitlab-org/gitlab/-/issues/339348
stub_feature_flags(new_header_search: false)
# Disable the override flag in order to enable the feature by default.
# See https://docs.gitlab.com/ee/development/feature_flags/#selectively-disable-by-actor
stub_feature_flags(surface_environment_creation_failure_override: false)
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
else
unstub_all_feature_flags
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment