diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 0000000..2229364 --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,44 @@ +--- +name: Integration tests + +on: + push: + branches: &branches + - "master" + - "release/**" + paths-ignore: &paths-ignore + - ".github/**" + - ".run/**" + - ".vscode/**" + - "docs/**" + - "examples/**" + - "charts/**" + - "hack/**" + - "ui/static/**" + - "**/*.md" + - "**/*.gitignore" + - "**/*.gitattributes" + - "Makefile" + - ".golangci.yml" + pull_request: + branches: *branches + paths-ignore: *paths-ignore + workflow_dispatch: + +jobs: + ci_job: + name: test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + cache: true + + - name: Run integration tests + run: make test-integ + shell: bash diff --git a/.run/markdown.run.xml b/.run/markdown.run.xml index 1c2f3d8..a67cb35 100644 --- a/.run/markdown.run.xml +++ b/.run/markdown.run.xml @@ -2,7 +2,7 @@ - + diff --git a/Makefile b/Makefile index d03f880..5c8c544 100644 --- a/Makefile +++ b/Makefile @@ -37,3 +37,10 @@ snapshot: test-cov: go test -coverprofile=$(COV_REPORT) ./... go tool cover -html=$(COV_REPORT) + +.PHONY: test-integ +test-integ: build + RELIMPACT_BIN=./bin/relimpact \ + rm -rf test/integration/bin \ + && mv bin/ test/integration \ + && go test ./test/integration -tags=integration -v diff --git a/test/integration/exec_util.go b/test/integration/exec_util.go new file mode 100644 index 0000000..bc0979b --- /dev/null +++ b/test/integration/exec_util.go @@ -0,0 +1,44 @@ +//go:build integration + +package integration + +import ( + "bytes" + "fmt" + "os/exec" + "strings" +) + +// Without stdin +// out, err := runCmd("echo", "hello world") +// fmt.Printf("output: %q, err: %v\n", out, err) +func runCmd(name string, args ...string) (string, error) { + cmd := exec.Command(name, args...) + + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("%w: %s", err, stderr.String()) + } + return out.String(), nil +} + +// With stdin +// out, err = runCmdWithStdin("hello from stdin\n", "cat") +// fmt.Printf("output: %q, err: %v\n", out, err) +func runCmdWithStdin(stdin string, name string, args ...string) (string, error) { + cmd := exec.Command(name, args...) + + cmd.Stdin = strings.NewReader(stdin) + + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("%w: %s", err, stderr.String()) + } + return out.String(), nil +} diff --git a/test/integration/md_test.go b/test/integration/md_test.go new file mode 100644 index 0000000..dd874ed --- /dev/null +++ b/test/integration/md_test.go @@ -0,0 +1,36 @@ +//go:build integration + +package integration + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func relimpactBin() string { + // TODO: also with envs + return "./bin/relimpact" +} + +func relimpactRepoURL() string { + return "https://github.com/hashmap-kz/relimpact.git" +} + +func TestExpected_Result1(t *testing.T) { + tmpDir := t.TempDir() + + _, err := runCmd("git", "clone", relimpactRepoURL(), tmpDir) + require.NoError(t, err) + + md, err := runCmd(relimpactBin(), "--old", "269945d", "--new", "5a0c267", "--greedy", "--dir", tmpDir) + require.NoError(t, err) + + readFile, err := os.ReadFile(filepath.Join("testdata", t.Name()+".md")) + require.NoError(t, err) + + expected := string(readFile) + require.Equal(t, expected, md) +} diff --git a/test/integration/testdata/TestExpected_Result1.md b/test/integration/testdata/TestExpected_Result1.md new file mode 100644 index 0000000..a825416 --- /dev/null +++ b/test/integration/testdata/TestExpected_Result1.md @@ -0,0 +1,261 @@ +# API compatibility report + +`269945d` -> `5a0c267` + +> **Breaking API changes detected.** Review before release. + +| Breaking | Changed | Removed | Added | Packages | +|---:|---:|---:|---:|---:| +| 1 | 0 | 1 | 45 | 7 | + +## Contents + +### Breaking changes + +- `github.com/hashmap-kz/relimpact` - 3 + +### New API + +- `github.com/hashmap-kz/relimpact/internal/diffs` - 51 +- `github.com/hashmap-kz/relimpact/internal/loggr` - 20 +- `github.com/hashmap-kz/relimpact/internal/testutils` - 4 +- `github.com/hashmap-kz/relimpact/cmd` - 2 +- `github.com/hashmap-kz/relimpact/internal/gitutils` - 2 +- `github.com/hashmap-kz/relimpact/internal/version` - 1 + +## Breaking changes + +### `github.com/hashmap-kz/relimpact` + +#### Removed API + +**type GoPackage struct** + +```diff +type GoPackage struct { +- Export []string +- ImportPath string +- Name string +} +``` + +## New API + +### `github.com/hashmap-kz/relimpact/internal/diffs` + +#### Added API + +**Functions** + +```diff ++ DiffAPI(map[string]diffs.APIPackage, map[string]diffs.APIPackage) *diffs.APIDiff ++ DiffDocs(string, string) []diffs.DocDiff ++ DiffGoMod(string, string) diffs.GoModDiff ++ DiffOther(string, string, string, []string) *diffs.OtherFilesDiffSummary ++ FormatAllDocDiffs([]diffs.DocDiff) string ++ SnapshotAPI(string) map[string]diffs.APIPackage +``` + +**type APIDiff struct** + +```diff +type APIDiff struct { ++ ConstsAdded []diffs.APIDiffRes ++ ConstsRemoved []diffs.APIDiffRes ++ FieldsAdded []diffs.APIDiffRes ++ FieldsRemoved []diffs.APIDiffRes ++ FuncsAdded []diffs.APIDiffRes ++ FuncsRemoved []diffs.APIDiffRes ++ MethodsAdded []diffs.APIDiffRes ++ MethodsRemoved []diffs.APIDiffRes ++ PackagesAdded []string ++ PackagesRemoved []string ++ TypesAdded []diffs.APIDiffRes ++ TypesRemoved []diffs.APIDiffRes ++ VarsAdded []diffs.APIDiffRes ++ VarsRemoved []diffs.APIDiffRes +} +``` + +**type APIDiffRes struct** + +```diff +type APIDiffRes struct { ++ Label string ++ Path string ++ X string +} +``` + +**type APIPackage struct** + +```diff +type APIPackage struct { ++ Consts []string ++ Funcs []string ++ Types map[string]diffs.APIType ++ Vars []string +} +``` + +**type APIType struct** + +```diff +type APIType struct { ++ Fields []string ++ Kind string ++ Methods []string +} +``` + +**type DocDiff struct** + +```diff +type DocDiff struct { ++ File string ++ HeadingsAdded []string ++ HeadingsRemoved []string ++ ImagesAdded []string ++ ImagesRemoved []string ++ LinksAdded []string ++ LinksRemoved []string ++ SectionWordChange []string +} +``` + +**type DocInfo struct** + +```diff +type DocInfo struct { ++ Headings []string ++ Images []string ++ Links []string ++ SectionWord map[string]int +} +``` + +**type GoModDiff struct** + +```diff +type GoModDiff struct { ++ DependenciesAdded []string ++ DependenciesRemoved []string ++ DependenciesUpdated []string +} +``` + +**type OtherFileDiff struct** + +```diff +type OtherFileDiff struct { ++ Added []string ++ Ext string ++ Modified []string ++ Other []string ++ Removed []string +} +``` + +**type OtherFilesDiffSummary struct** + +```diff +type OtherFilesDiffSummary struct { ++ Diffs []diffs.OtherFileDiff +} +``` + +### `github.com/hashmap-kz/relimpact/internal/loggr` + +#### Added API + +**Types** + +```diff ++ LogLevel +``` + +**Functions** + +```diff ++ Debug(string) ++ Debugf(string, []any) ++ Error(string) ++ Errorf(string, []any) ++ Fatal(string) ++ Fatalf(string, []any) ++ Info(string) ++ Infof(string, []any) ++ Init(loggr.LogLevel, string) ++ Trace(string) ++ Tracef(string, []any) ++ Warn(string) ++ Warnf(string, []any) +``` + +**Variables** + +```diff ++ Logger *loggr.LevelLogger +``` + +**Constants** + +```diff ++ LevelDebug = 1 ++ LevelError = 4 ++ LevelInfo = 2 ++ LevelTrace = 0 ++ LevelWarn = 3 +``` + +**type LevelLogger struct** + +```diff +type LevelLogger struct { +} +``` + +### `github.com/hashmap-kz/relimpact/internal/testutils` + +#### Added API + +**Functions** + +```diff ++ ProjectRoot(*testing.T) string ++ ReadTestData(*testing.T, string) []byte ++ RunGit(*testing.T, string, []string) ++ RunGo(*testing.T, string, []string) +``` + +### `github.com/hashmap-kz/relimpact/cmd` + +#### Added API + +**Functions** + +```diff ++ CreateChangelog(string, string, string) string ++ CreateChangelogSequential(string, string, string) string +``` + +### `github.com/hashmap-kz/relimpact/internal/gitutils` + +#### Added API + +**Functions** + +```diff ++ CheckoutWorktree(string, string) string ++ CleanupWorktree(string, string) +``` + +### `github.com/hashmap-kz/relimpact/internal/version` + +#### Added API + +**Variables** + +```diff ++ Version string +```