Add initial stuff

This commit is contained in:
Julian Bensch 2023-01-12 14:49:16 +01:00
parent da828b28ba
commit 2bf77b207e
4 changed files with 348 additions and 0 deletions

110
.golangci.yml Normal file
View File

@ -0,0 +1,110 @@
timeout: 30m
output:
format: tab
sort-results: true
linters:
disable-all: true
enable:
# checks whether HTTP response body is closed successfully
- bodyclose
# Tool for code clone detection
- dupl
# Errcheck is a program for checking for unchecked errors in go programs.
# These unchecked errors can be critical bugs in some cases
- errcheck
# Tool for detection of long functions
- funlen
# Checks that no init functions are present in Go code
- gochecknoinits
# Computes and checks the cyclomatic complexity of functions
- gocyclo
# Gofmt checks whether code was gofmt-ed.
# By default this tool runs with -s option to check for code simplification
- gofmt
# In addition to fixing imports, goimports also formats your code in the same style as gofmt.
- goimports
# Detects when assignments to existing variables are not used
- ineffassign
# Checks Go code for unused constants, variables, functions and types
- unused
# Inspects source code for security problems
- gosec
linters-settings:
gocyclo:
# Minimal code complexity to report.
# Default: 30 (but we recommend 10-20)
min-complexity: 40
funlen:
# Checks the number of lines in a function.
# If lower than 0, disable the check.
# Default: 60
lines: 200
# Checks the number of statements in a function.
# If lower than 0, disable the check.
# Default: 40
statements: 200
gofmt:
# Simplify code: gofmt with `-s` option.
# Default: true
simplify: true
goconst:
# Minimal length of string constant.
# Default: 3
min-len: 3
# Minimum occurrences of constant string count to trigger issue.
# Default: 3
min-occurrences: 2
# Ignore test files.
# Default: false
ignore-tests: true
# Look for existing constants matching the values.
# Default: true
match-constant: false
# Search also for duplicated numbers.
# Default: false
numbers: true
# Minimum value, only works with goconst.numbers
# Default: 3
min: 2
# Maximum value, only works with goconst.numbers
# Default: 3
max: 2
# Ignore when constant is not used as function argument.
# Default: true
ignore-calls: false
goimports:
# Put imports beginning with prefix after 3rd-party packages.
# It's a comma-separated list of prefixes.
# Default: ""
local-prefixes: ""
issues:
# Report all issues
max-issues-per-linter: 0
max-same-issues: 0
# Disable some
exclude-rules:
- path: main.go|app.go
linters:
- funlen
- path: _test\.go|mock|integration
linters:
- funlen
- goconst

25
dockerfile Normal file
View File

@ -0,0 +1,25 @@
FROM golang:alpine AS builder
# Set necessary environmet variables needed for our image
ENV GO111MODULE=on \
GOOS=linux \
GOARCH=amd64 \
CGO_ENABLED=0
WORKDIR /build
# Add the required build libraries
# Nothing here!
# Copy and download dependency using go mod
ADD ./src/go.* /build/
RUN go mod download
# Copy sources to build container
ADD ./src /build/
# Build the application
WORKDIR /build
RUN ls -al
RUN go build -a -tags musl -o /build/app
######################################
FROM alpine:3
LABEL AUTHOR="AUTHOR"
#RUN apk --no-cache add curl
USER nobody
COPY --from=builder --chown=nobody /build/app /custom/app
ENTRYPOINT [ "/custom/app" ]

35
drone.yml Normal file
View File

@ -0,0 +1,35 @@
---
kind: pipeline
type: docker
name: default
steps:
# Build docker image and push to docker hub
- name: build
image: golang:1.19-alpine
pull: if-not-exists
commands:
- go build -o cmd/app main.go
- name: "lint"
image: golangci/golangci-lint:v1.50
pull: if-not-exists
commands:
- golangci-lint run
- name: "add binary release to gitea"
image: plugins/gitea-release
api_key: 5353c40cd692fd01f243b1f935af1962ff03bfd6
base_url: https://gitea.linuxcode.net
files: cmd/*
- name: "build and publish docker image"
image: plugins/docker
settings:
registry: gitea.linuxcode.net
repo: gitea.linuxcode.net/drblury/oapi-type-definitions-extractor
dockerfile: dockerfile
tags: latest
username:
from_secret: drone_docker_username
password:
from_secret: drone_docker_password

178
main.go Normal file
View File

@ -0,0 +1,178 @@
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: go run main.go <input_directory> <output_directory>")
return
}
inputDir := os.Args[1]
outputDir := os.Args[2]
files, err := getGoFiles(inputDir)
if err != nil {
fmt.Println(err)
return
}
for _, file := range files {
typeDecls, importDecls, err := extractTypes(file)
if err != nil {
fmt.Println(err)
continue
}
// Filter out structs with "Nullable" at the beginning of their names.
typeDecls = filterNullableTypes(typeDecls)
// Generate the adapted file name by inserting the "_adapted" string before the ".go" extension of the original file name.
adaptedFile := strings.Replace(filepath.Base(file), ".go", "_adapted.go", 1)
adaptedFile = filepath.Join(outputDir, adaptedFile)
// Write the struct declarations and import declarations to the adapted file.
err = writeStruct(typeDecls, importDecls, adaptedFile)
if err != nil {
fmt.Println(err)
continue
}
// Reformat the adapted file using gofmt.
err = runGoImports(adaptedFile)
if err != nil {
fmt.Println(err)
continue
}
}
}
// getGoFiles returns a list of .go files in the given directory.
func getGoFiles(dir string) ([]string, error) {
var files []string
f, err := os.Open(dir)
if err != nil {
return nil, err
}
defer f.Close()
fi, err := f.Readdir(-1)
if err != nil {
return nil, err
}
for _, file := range fi {
if !file.IsDir() && strings.HasSuffix(file.Name(), ".go") {
// Concatenate the directory path and the file name to get the full path.
files = append(files, dir+"/"+file.Name())
}
}
return files, nil
}
// filterNullableTypes filters out structs with "Nullable" at the beginning of their names.
func filterNullableTypes(structDecls []string) []string {
var filteredStructDecls []string
for _, s := range structDecls {
// Check if the struct name starts with "Nullable".
if !strings.HasPrefix(s, "type Nullable") {
filteredStructDecls = append(filteredStructDecls, s)
}
}
return filteredStructDecls
}
// extractTypes reads a .go file and returns a list of type declarations and a list of import declarations.
func extractTypes(file string) ([]string, []string, error) {
var typeDecls []string
var importDecls []string
f, err := os.Open(file)
if err != nil {
return nil, nil, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
var typeDecl, importDecl string
inStruct, inImport := false, false
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "import") {
inImport = true
importDecl = line + "\n"
} else if inImport && (line == "" || strings.HasPrefix(line, ")")) {
importDecl += line + "\n"
inImport = false
importDecls = append(importDecls, importDecl)
} else if inImport {
importDecl += line + "\n"
} else if strings.HasPrefix(line, "type") {
inStruct = true
typeDecl = line + "\n"
} else if inStruct && strings.HasPrefix(line, "}") {
typeDecl += line + "\n"
typeDecls = append(typeDecls, typeDecl)
inStruct = false
} else if inStruct {
typeDecl += line + "\n"
}
}
if err := scanner.Err(); err != nil {
return nil, nil, err
}
return typeDecls, importDecls, nil
}
// writeStruct writes the given struct declarations and import declarations to a new file with the given name.
func writeStruct(structDecls []string, importDecls []string, file string) error {
f, err := os.Create(file)
if err != nil {
return err
}
defer f.Close()
// Add the package dto declaration at the top of the file.
_, err = io.WriteString(f, "package dto\n\n")
if err != nil {
return err
}
// Write the import declarations to the file.
for _, importDecl := range importDecls {
_, err = io.WriteString(f, importDecl)
if err != nil {
return err
}
}
// Write the struct declarations to the file.
for _, s := range structDecls {
_, err = io.WriteString(f, s)
if err != nil {
return err
}
}
return nil
}
// runimports reformats the given file using the goimports tool.
func runGoImports(file string) error {
cmd := exec.Command("goimports", "-w", file)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("%s: %s", err, output)
}
return nil
}