diff options
Diffstat (limited to 'danger/saas_feature/Dangerfile')
-rw-r--r-- | danger/saas_feature/Dangerfile | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/danger/saas_feature/Dangerfile b/danger/saas_feature/Dangerfile new file mode 100644 index 00000000000..5b1eed7078c --- /dev/null +++ b/danger/saas_feature/Dangerfile @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +# rubocop:disable Style/SignalException + +SEE_DOC = "see the [SaaS feature documentation](https://docs.gitlab.com/ee/development/ee_features.html#saas-only-feature)." +LABEL = "saas_feature" +EXISTS_LABEL = "#{LABEL}::exists".freeze +SKIPPED_LABEL = "#{LABEL}::skipped".freeze + +SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT.freeze + ```suggestion + group: "%<group>s" + ``` + + #{SEE_DOC.capitalize} +SUGGEST_COMMENT + +ENFORCEMENT_WARNING = <<~WARNING_MESSAGE.freeze + There were no new or modified SaaS feature YAML files detected in this MR. + + For guidance on when to use a SaaS feature, please #{SEE_DOC} +WARNING_MESSAGE + +def check_yaml(saas_feature) + mr_group_label = helper.group_label + + message_for_missing_group!(saas_feature: saas_feature, mr_group_label: mr_group_label) if saas_feature.group.nil? +rescue Psych::Exception + # YAML could not be parsed, fail the build. + fail "#{helper.html_link(saas_feature.path)} isn't valid YAML! #{SEE_DOC.capitalize}" +rescue StandardError => e + warn "There was a problem trying to check the SaaS feature file. Exception: #{e.class.name} - #{e.message}" +end + +def message_for_missing_group!(saas_feature:, mr_group_label:) + mr_line = saas_feature.raw.lines.find_index do |line| + line.start_with?('group:') + end + + if mr_line + markdown(format(SUGGEST_MR_COMMENT, group: mr_group_label), file: saas_feature.path, line: mr_line.succ) + elsif mr_group_label + warn %( + Consider setting `group: "#{mr_group_label}"` in #{helper.html_link(saas_feature.path)}. #{SEE_DOC.capitalize} + ) + else + warn "Consider setting `group` in #{helper.html_link(saas_feature.path)}. #{SEE_DOC.capitalize}" + end +end + +def message_for_group!(saas_feature:, mr_group_label:) + return if saas_feature.group_match_mr_label?(mr_group_label) + + if mr_group_label + fail %(`group` is set to ~"#{saas_feature.group}" in #{helper.html_link(saas_feature.path)}, + which does not match ~"#{mr_group_label}" set on the MR!) + end + + helper.labels_to_add << saas_feature.group +end + +def added_files + saas_feature.files(change_type: :added) +end + +def modified_files + saas_feature.files(change_type: :modified) +end + +def file_added? + added_files.any? +end + +def file_modified? + modified_files.any? +end + +def file_added_or_modified? + file_added? || file_modified? +end + +def mr_has_backend_or_frontend_changes? + changes = helper.changes_by_category + changes.has_key?(:backend) || changes.has_key?(:frontend) +end + +def mr_missing_status_label? + helper.mr_labels.none? { |label| label.start_with?(LABEL) } +end + +added_files.each do |saas_feature| + check_yaml(saas_feature) +end + +if !helper.security_mr? && mr_has_backend_or_frontend_changes? + if file_added_or_modified? && !helper.mr_has_labels?(EXISTS_LABEL) + # SaaS feature config file touched in this MR, so let's add the label to avoid the warning. + helper.labels_to_add << EXISTS_LABEL + end + + warn ENFORCEMENT_WARNING if mr_missing_status_label? +end + +# rubocop:enable Style/SignalException |