diff --git a/.gitignore b/.gitignore index b466dba..f4a1cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ *.out # Dependency directories (remove the comment below to include it) -# vendor/ +vendor/ # Go workspace file go.work diff --git a/.vscode/settings.json b/.vscode/settings.json index ba29104..4c0048e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,26 @@ { "cSpell.words": [ - "drawio" + "Бадяев", + "Версионирование", + "версионируется", + "Alek", + "Childs", + "drawio", + "errcheck", + "gocov", + "GOPATH", + "honnef", + "jstemmer", + "kisielk", + "matm", + "mousesoft", + "mxfile", + "nxfile", + "sashamelentyev", + "staticcheck", + "stretchr", + "tamerh", + "usestdlibvars", + "xmlparser" ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index de4cb3b..2b8d292 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,102 +6,29 @@ { "label": "build", "type": "shell", - "command": "make vendor build", - "group": "build", - "icon": { - "id": "briefcase", - "color": "terminal.ansiGreen" - } - }, - { - "label": "dist", - "type": "shell", - "command": "make build dist", - "group": "build", - "icon": { - "id": "briefcase", - "color": "terminal.ansiBlue" - }, - "options": { - "env": { - "GO_OPT": "" - } - } - }, - { - "label": "doc HTML", - "type": "shell", - "command": "make doc", - "group": "build", - "icon": { - "id": "book", - "color": "terminal.ansiBlue" - }, - "options": { - "env": { - "DOC_FORMAT": "html" - } - } - }, - { - "label": "doc PDF", - "type": "shell", - "command": "make doc", - "group": "build", - "icon": { - "id": "book", - "color": "terminal.ansiRed" - }, - "options": { - "env": { - "DOC_FORMAT": "pdf" - } - } + "command": "make build", + "group": "build" }, { "label": "test", "type": "shell", "command": "make test", - "group": "test", - "icon": { - "id": "beaker", - "color": "terminal.ansiGreen" - } + "group": "test" }, { "label": "coverage", "type": "shell", "command": "make coverage", "group": "test", - "icon": { - "id": "beaker", - "color": "terminal.ansiGreen" - } - }, - { - "label": "coverage HTML", - "type": "shell", - "command": "make coverage", - "group": "test", - "icon": { - "id": "beaker", - "color": "terminal.ansiBlue" - }, "options": { - "env": { - "EXPORT_RESULT": "true" - } + "env": { "EXPORT_RESULT": "true" } } }, { "label": "clean", "type": "shell", "command": "make clean", - "group": "build", - "icon": { - "id": "trash", - "color": "terminal.ansiBlack" - } + "group": "build" } ] } \ No newline at end of file diff --git a/README.md b/README.md index 7ec9dc2..e8923fd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,138 @@ # Go Draw.io Exporter +Автор: Алексей Бадяев + Экспортирует все диаграммы из файла формата `Draw.io`. Для работы необходимо наличие приложения `drawio-desktop`. + +## Разработка + +Для удобного редактирования, сборки, отладки и тестирования проекта в локальном +окружении программиста необходимо выполнить следующие действия: + +1. Клонировать репозиторий проекта в папку `$GOPATH/src/git.mousesoft.ru/ms/`. +2. Установить все Go-пакеты, от которых зависит этот проект + (см. следующий раздел). +3. Если предполагается формирование отчёта о покрытии кода модульными тестами, + то нужно установить необходимые для этого пакеты + (см. раздел [Тестирование](#тестирование) далее). + +### Структура проекта + +Структура дерева файлов проекта соответствует рекомендациям в +[Standard Go Project Layout](https://github.com/golang-standards/project-layout): + +- `build` - Сборка и непрерывная интеграция (Continuous Integration, *CI*). +- `cmd` - Основные приложения проекта. Имя директории для каждого приложения + должно совпадать с именем исполняемого файла, который вы хотите собрать. +- `pkg` - Код библиотек, пригодных для использования в сторонних приложениях. +- `scripts` - Скрипты для сборки, установки, анализа и прочих операций над проектом. + +### Линтеры + +Отформатировать все исходные тексты проекта в соответствии со стандартом Go +можно командой: + + go fmt ./... + +В проекте используются следующие линтеры: + +- [go vet](https://pkg.go.dev/cmd/vet) +- [errcheck](https://github.com/kisielk/errcheck) + Команда установки линтера: `go install github.com/kisielk/errcheck@latest`. +- [staticcheck](https://staticcheck.io/) + Команда установки линтера: `go install honnef.co/go/tools/cmd/staticcheck@latest`. +- [usestdlibvars](https://github.com/sashamelentyev/usestdlibvars) + Команда установки линтера: `go install github.com/sashamelentyev/usestdlibvars@latest` + +Все линтеры проекта можно запустить командой: + + make lint + +## Компиляция + +Все зависимости устанавливаются в папку `vendor` командой: + + make vendor + +Собрать исполняемый файл сервиса можно командой: + + make build + +После успешного выполнения команды в папке `out/bin` в корне проекта появится +исполняемые бинарные файлы. + +### Версия продукта + +Проект версионируется в соответствии с документом +[Семантическое Версионирование 2.0.0](https://semver.org/lang/ru/). +Наименование версии продукта считывается во время сборки проекта из переменной +окружения `VERSION`. Если при сборке переменная окружения `VERSION` не задана, +то номер версии формируется автоматически из системы контроля версий на основании +последнего тэга, наличия коммитов после него и текущего состояния репозитория +командой: + + git describe --always --tags --dirty + +При этом если проект собирается из ветки выпуска вида `release/1.2.3`, то +то версия принимает вид `v1.2.3RC` (что означает "Release Candidate"). + +Для получения версии приложения необходимо запустить его с параметром `--version`: + + drawio-export --version + +## Тестирование + +Статический анализ всех исходных текстов проекта можно выполнить командами: + + go vet ./... + +Модульные тесты проекта можно запустить командой: + + make test + +### Отчёт о тестировании + +Отчёт о выполнении тестов можно получить, запустив в папке программы команду: + + make test + +Для получения отчёта о выполнении тестов в формате *JUnit XML* необходимо +установить инструмент: + + go install github.com/jstemmer/go-junit-report@latest + +Получить отчёт можно командой: + + EXPORT_RESULT=true make test + +После успешного выполнения команды появится файл `out/junit-report.xml` +с отчётом в формате [JUnit](https://junit.org). + +### Покрытие кода тестами + +Для получения отчётов о покрытии кода тестами необходимо установить следующие +инструменты: + + go install github.com/axw/gocov/gocov@latest + go install github.com/matm/gocov-html/cmd/gocov-html@latest + go install github.com/AlekSi/gocov-xml@latest + +Для получения отчёта о покрытии проекта тестами в консоли нужно выполнить +команду: + + make coverage + +Получить отчёт о покрытии кода тестами в формате *HTML* можно командой: + + EXPORT_RESULT=true make coverage + +После успешного выполнения этой команды файл `out/coverage.html` будет содержать +отчёт о покрытии кода проекта модульными тестами в формате *HTML*. + +Получить отчёт о покрытии кода тестами в формате *XML* можно командой: + + EXPORT_RESULT=true COVERAGE_FORMAT=xml make coverage + +После успешного выполнения этой команды файл `out/coverage.xml` будет содержать +отчёт о покрытии кода проекта модульными тестами в формате *XML*. diff --git a/go.mod b/go.mod index ae6c96b..6453683 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,13 @@ module git.mousesoft.ru/ms/drawio-exporter go 1.20 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/testify v1.8.2 // indirect + github.com/tamerh/xml-stream-parser v1.4.0 // indirect + github.com/tamerh/xpath v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..efdd76b --- /dev/null +++ b/go.sum @@ -0,0 +1,21 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tamerh/xml-stream-parser v1.4.0 h1:Vb1ZqshlXi53vvUBzZUdEsEJBvnKVWhfrGEJhfQABfc= +github.com/tamerh/xml-stream-parser v1.4.0/go.mod h1:lrpNpthn/iYpnyICCe4KwJSANxywFIfSvsqokQOV9q0= +github.com/tamerh/xpath v1.0.0 h1:NccMES/Ej8slPCFDff73Kf6V1xu9hdbuKf2RyDsxf5Q= +github.com/tamerh/xpath v1.0.0/go.mod h1:t0wnh72FQlOVEO20f2Dl3EoVxso9GnLREh1WTpvNmJQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/drawio/export.go b/pkg/drawio/export.go new file mode 100644 index 0000000..1e48b04 --- /dev/null +++ b/pkg/drawio/export.go @@ -0,0 +1,32 @@ +package drawio + +import ( + "bufio" + "fmt" + "io" + + xmlparser "github.com/tamerh/xml-stream-parser" +) + +// Разбирает данные и возвращает срез имён диаграмм в них +func Diagrams(reader io.Reader) ([]string, error) { + var ( + result = []string{} + br = bufio.NewReader(reader) + parser = xmlparser.NewXMLParser( + br, "mxfile", "diagram", + ).ParseAttributesOnly("diagram") + ) + for xml := range parser.Stream() { + if xml.Err != nil { + return result, xml.Err + } + fmt.Println(xml.Name) + if items, ok := xml.Childs["diagram"]; ok { + for _, item := range items { + result = append(result, item.Attrs["name"]) + } + } + } + return result, nil +} diff --git a/pkg/drawio/export_test.go b/pkg/drawio/export_test.go new file mode 100644 index 0000000..55f66b7 --- /dev/null +++ b/pkg/drawio/export_test.go @@ -0,0 +1,63 @@ +package drawio_test + +import ( + "strings" + "testing" + + "git.mousesoft.ru/ms/drawio-exporter/pkg/drawio" + "github.com/stretchr/testify/assert" +) + +// Тестовые данные +var testData = []struct { + name string // Наименование теста + source string // Данные файла с диаграммами + diagrams []string // Срез имён диаграмм +}{ + { + name: "positive case", + source: ` + + + + + + + + + + + + +`, + diagrams: []string{"1", "2", "3"}, + }, + { + name: "invalid source", + source: ` + + + + + + + + + + + + +`, + diagrams: []string{}, + }, +} + +func TestDiagrams(t *testing.T) { + for _, test := range testData { + t.Run(test.name, func(t *testing.T) { + diagrams, err := drawio.Diagrams(strings.NewReader(test.source)) + assert.NoError(t, err) + assert.ElementsMatch(t, test.diagrams, diagrams) + }) + } +}