Загрузка данных


dmitriev-aal@VDI-Dmitriev-A:~/Desktop/appfarm/ci-cd/project-verifier$ sed -n '1,260p' internal/verifications/common/mergerequest.go
package common

import (
	"strings"

	"gitlab.rshbdev.ru/appfarm/ci-cd/project-verifier/internal/matching"
	"gitlab.rshbdev.ru/appfarm/ci-cd/project-verifier/pkg"
	"gitlab.rshbdev.ru/appfarm/ci-cd/project-verifier/pkg/verifier"
)

type MergeRequest struct {
	GlobalId string
}

func (v *MergeRequest) Id() string { return v.GlobalId }
func (v *MergeRequest) Name() string {
	return "Проверки MR: описание и ссылка на задачу"
}

func (v *MergeRequest) ShouldApply(configuration *pkg.Config) bool {
	return matching.AnyMatch(configuration.ProjectTypes, pkg.PtCommon) && strings.TrimSpace(configuration.CIMergeRequestInternalID) != ""
}

// Проверка на минимальную длину описания MR
func (v *MergeRequest) CheckMRDescriptionLength(configuration *pkg.Config) verifier.Check {
	return verifier.Check{
		Id:   "001",
		Name: "Минимальная длина описания MR",
		Predicate: func() verifier.CheckResult {
			minimumDescriptionLength := configuration.MergeRequestCommentMinLength
			if minimumDescriptionLength <= 0 {
				return verifier.Skip("Проверка минимальной длины описания MR отключена")
			}

			mergeRequestDescription := configuration.CIMergeRequestDescription
			actualLength := len([]rune(strings.TrimSpace(mergeRequestDescription)))
			if actualLength < minimumDescriptionLength {
				return verifier.Fail(
					"Описание MR должно быть не короче %d символов. Фактически: %d. Дополните описание изменений.",
					minimumDescriptionLength, actualLength,
				)
			}
			return verifier.Success()
		},
	}
}

// Проверка наличия ссылки на задачу в описании MR
func (v *MergeRequest) CheckMRContainsTaskLink(configuration *pkg.Config) verifier.Check {
	return verifier.Check{
		Id:   "002",
		Name: "Описание MR содержит ссылку на задачу",
		Predicate: func() verifier.CheckResult {
			linkBaseURL := strings.TrimSpace(configuration.MergeRequestCommentLinkBaseURL)
			if linkBaseURL == "" {
				return verifier.Skip("Проверка наличия ссылки в описании MR отключена")
			}

			mergeRequestDescription := configuration.CIMergeRequestDescription
			if !strings.Contains(mergeRequestDescription, linkBaseURL) {
				return verifier.Fail(
					"В описании MR отсутствует ссылка на задачу. Путь к задаче должен начинаться с '%s'. Добавьте ссылку вида '%s/CKPR-123'.",
					linkBaseURL, linkBaseURL,
				)
			}
			return verifier.Success()
		},
	}
}
dmitriev-aal@VDI-Dmitriev-A:~/Desktop/appfarm/ci-cd/project-verifier$ sed -n '1,240p' internal/verifications/common/mergerequest_test.go
package common

import (
	"fmt"
	"strings"
	"testing"

	"gitlab.rshbdev.ru/appfarm/ci-cd/project-verifier/pkg"
	"gitlab.rshbdev.ru/appfarm/ci-cd/project-verifier/pkg/verifier"
)

var testMergeRequest = &MergeRequest{}

func Test_CheckMRDescriptionLength(t *testing.T) {
	tests := []struct {
		name string
		fn   func() (bool, verifier.CheckResult)
	}{
		{
			name: "Длина описания больше порога",
			fn: func() (bool, verifier.CheckResult) {
				minLen := 50
				desc := strings.Repeat("a", 60)

				want := verifier.CheckResult{Passed: true}

				result := testMergeRequest.CheckMRDescriptionLength(
					&pkg.Config{
						ProjectTypes:                 []string{pkg.PtCommon},
						CIMergeRequestInternalID:     "140",
						CIMergeRequestDescription:    desc,
						MergeRequestCommentMinLength: minLen,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "Длина описания равна порогу",
			fn: func() (bool, verifier.CheckResult) {
				minLen := 20
				desc := strings.Repeat("б", 20)

				want := verifier.CheckResult{Passed: true}

				result := testMergeRequest.CheckMRDescriptionLength(
					&pkg.Config{
						ProjectTypes:                 []string{pkg.PtCommon},
						CIMergeRequestInternalID:     "140",
						CIMergeRequestDescription:    desc,
						MergeRequestCommentMinLength: minLen,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "Длина описания меньше порога",
			fn: func() (bool, verifier.CheckResult) {
				minLen := 50
				desc := "коротко"

				want := verifier.CheckResult{
					Passed: false,
					Message: fmt.Sprintf(
						"Описание MR должно быть не короче %d символов. Фактически: %d. Дополните описание изменений.",
						minLen, len([]rune(strings.TrimSpace(desc))),
					),
				}

				result := testMergeRequest.CheckMRDescriptionLength(
					&pkg.Config{
						ProjectTypes:                 []string{pkg.PtCommon},
						CIMergeRequestInternalID:     "140",
						CIMergeRequestDescription:    desc,
						MergeRequestCommentMinLength: minLen,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "Порог отключен",
			fn: func() (bool, verifier.CheckResult) {
				want := verifier.CheckResult{
					Passed:  true,
					Message: "Проверка минимальной длины описания MR отключена",
				}

				result := testMergeRequest.CheckMRDescriptionLength(
					&pkg.Config{
						ProjectTypes:                 []string{pkg.PtCommon},
						CIMergeRequestInternalID:     "140",
						CIMergeRequestDescription:    "коротко",
						MergeRequestCommentMinLength: 0,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
	}

	for _, test := range tests {
		ok, was := test.fn()
		if !ok {
			t.Errorf("Название: %s, Результат: %s; %v", test.name, was.Message, was.Passed)
		}
	}
}

func Test_CheckMRContainsJiraLink(t *testing.T) {
	tests := []struct {
		name string
		fn   func() (bool, verifier.CheckResult)
	}{
		{
			name: "В описании нет ссылки на задачу",
			fn: func() (bool, verifier.CheckResult) {
				base := "https://sdlc.go.rshbank.ru/jira/browse"
				desc := "Описание изменения без какой-либо Jira ссылки"

				want := verifier.CheckResult{
					Passed: false,
					Message: fmt.Sprintf(
						"В описании MR отсутствует ссылка на задачу. Путь к задаче должен начинаться с '%s'. Добавьте ссылку вида '%s/CKPR-123'.",
						base, base,
					),
				}

				result := testMergeRequest.CheckMRContainsTaskLink(
					&pkg.Config{
						ProjectTypes:                   []string{pkg.PtCommon},
						CIMergeRequestInternalID:       "140",
						CIMergeRequestDescription:      desc,
						MergeRequestCommentLinkBaseURL: base,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "В описании есть ссылка на задачу",
			fn: func() (bool, verifier.CheckResult) {
				base := "https://sdlc.go.rshbank.ru/jira/browse"
				desc := "Правка логики. Ссылка: https://sdlc.go.rshbank.ru/jira/browse/KEY-123"

				want := verifier.CheckResult{Passed: true}

				result := testMergeRequest.CheckMRContainsTaskLink(
					&pkg.Config{
						ProjectTypes:                   []string{pkg.PtCommon},
						CIMergeRequestInternalID:       "140",
						CIMergeRequestDescription:      desc,
						MergeRequestCommentLinkBaseURL: base,
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "Базовый путь не задан",
			fn: func() (bool, verifier.CheckResult) {
				want := verifier.CheckResult{
					Passed:  true,
					Message: "Проверка наличия ссылки в описании MR отключена",
				}

				result := testMergeRequest.CheckMRContainsTaskLink(
					&pkg.Config{
						ProjectTypes:                   []string{pkg.PtCommon},
						CIMergeRequestInternalID:       "140",
						CIMergeRequestDescription:      "Описание без ссылки",
						MergeRequestCommentLinkBaseURL: "",
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
					return false, predicate
				}
				return true, predicate
			},
		},
		{
			name: "Базовый путь состоит из пробелов",
			fn: func() (bool, verifier.CheckResult) {
				want := verifier.CheckResult{
					Passed:  true,
					Message: "Проверка наличия ссылки в описании MR отключена",
				}

				result := testMergeRequest.CheckMRContainsTaskLink(
					&pkg.Config{
						ProjectTypes:                   []string{pkg.PtCommon},
						CIMergeRequestInternalID:       "140",
						CIMergeRequestDescription:      "Описание без ссылки",
						MergeRequestCommentLinkBaseURL: "   ",
					},
				)

				predicate := result.Predicate()

				if want.Passed != predicate.Passed || want.Message != predicate.Message {
dmitriev-aal@VDI-Dmitriev-A:~/Desktop/appfarm/ci-cd/project-verifier$ grep -Rni 'MergeRequestCommentLinkBaseURL' --include='*.go' .
./pkg/config.go:79:	MergeRequestCommentLinkBaseURL string
./pkg/config.go:187:	result.MergeRequestCommentLinkBaseURL = strings.TrimSpace(context.String("merge-request-comment-link-base-url"))
./internal/verifications/common/mergerequest_test.go:159:						MergeRequestCommentLinkBaseURL: base,
./internal/verifications/common/mergerequest_test.go:184:						MergeRequestCommentLinkBaseURL: base,
./internal/verifications/common/mergerequest_test.go:209:						MergeRequestCommentLinkBaseURL: "",
./internal/verifications/common/mergerequest_test.go:234:						MergeRequestCommentLinkBaseURL: "   ",
./internal/verifications/common/mergerequest.go:54:			linkBaseURL := strings.TrimSpace(configuration.MergeRequestCommentLinkBaseURL)
dmitriev-aal@VDI-Dmitriev-A:~/Desktop/appfarm/ci-cd/project-verifier$ grep -RniE 'ссылк.*задач|link.*base|comment.*link|MergeRequest.*Link' \
>   --include='*.go' internal pkg
internal/verifications/common/mergerequest_test.go:141:			name: "В описании нет ссылки на задачу",
internal/verifications/common/mergerequest_test.go:149:						"В описании MR отсутствует ссылка на задачу. Путь к задаче должен начинаться с '%s'. Добавьте ссылку вида '%s/CKPR-123'.",
internal/verifications/common/mergerequest_test.go:154:				result := testMergeRequest.CheckMRContainsTaskLink(
internal/verifications/common/mergerequest_test.go:159:						MergeRequestCommentLinkBaseURL: base,
internal/verifications/common/mergerequest_test.go:172:			name: "В описании есть ссылка на задачу",
internal/verifications/common/mergerequest_test.go:179:				result := testMergeRequest.CheckMRContainsTaskLink(
internal/verifications/common/mergerequest_test.go:184:						MergeRequestCommentLinkBaseURL: base,
internal/verifications/common/mergerequest_test.go:204:				result := testMergeRequest.CheckMRContainsTaskLink(
internal/verifications/common/mergerequest_test.go:209:						MergeRequestCommentLinkBaseURL: "",
internal/verifications/common/mergerequest_test.go:229:				result := testMergeRequest.CheckMRContainsTaskLink(
internal/verifications/common/mergerequest_test.go:234:						MergeRequestCommentLinkBaseURL: "   ",
internal/verifications/common/mergerequest.go:17:	return "Проверки MR: описание и ссылка на задачу"
internal/verifications/common/mergerequest.go:48:// Проверка наличия ссылки на задачу в описании MR
internal/verifications/common/mergerequest.go:49:func (v *MergeRequest) CheckMRContainsTaskLink(configuration *pkg.Config) verifier.Check {
internal/verifications/common/mergerequest.go:52:		Name: "Описание MR содержит ссылку на задачу",
internal/verifications/common/mergerequest.go:54:			linkBaseURL := strings.TrimSpace(configuration.MergeRequestCommentLinkBaseURL)
internal/verifications/common/mergerequest.go:55:			if linkBaseURL == "" {
internal/verifications/common/mergerequest.go:60:			if !strings.Contains(mergeRequestDescription, linkBaseURL) {
internal/verifications/common/mergerequest.go:62:					"В описании MR отсутствует ссылка на задачу. Путь к задаче должен начинаться с '%s'. Добавьте ссылку вида '%s/CKPR-123'.",
internal/verifications/common/mergerequest.go:63:					linkBaseURL, linkBaseURL,
pkg/config.go:79:	MergeRequestCommentLinkBaseURL string
pkg/config.go:187:	result.MergeRequestCommentLinkBaseURL = strings.TrimSpace(context.String("merge-request-comment-link-base-url"))
dmitriev-aal@VDI-Dmitriev-A:~/Desktop/appfarm/ci-cd/project-verifier$