diff --git a/Makefile b/Makefile index a9468ef82..62a56f4d3 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,9 @@ $(TOOLS)/crosslink: PACKAGE=go.opentelemetry.io/build-tools/crosslink SEMCONVKIT = $(TOOLS)/semconvkit $(TOOLS)/semconvkit: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/semconvkit +VERIFYREADMES = $(TOOLS)/verifyreadmes +$(TOOLS)/verifyreadmes: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/verifyreadmes + GOLANGCI_LINT = $(TOOLS)/golangci-lint $(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/v2/cmd/golangci-lint @@ -68,7 +71,7 @@ GOVULNCHECK = $(TOOLS)/govulncheck $(TOOLS)/govulncheck: PACKAGE=golang.org/x/vuln/cmd/govulncheck .PHONY: tools -tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE) +tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(SEMCONVGEN) $(VERIFYREADMES) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE) # Virtualized python tools via docker @@ -322,5 +325,5 @@ lint-markdown: docker run --rm -u $(DOCKER_USER) -v "$(CURDIR):$(WORKDIR)" $(MARKDOWNIMAGE) -c $(WORKDIR)/.markdownlint.yaml $(WORKDIR)/**/*.md .PHONY: verify-readmes -verify-readmes: - ./verify_readmes.sh +verify-readmes: $(VERIFYREADMES) + $(VERIFYREADMES) diff --git a/internal/tools/verifyreadmes/main.go b/internal/tools/verifyreadmes/main.go new file mode 100644 index 000000000..ff0d4f4bc --- /dev/null +++ b/internal/tools/verifyreadmes/main.go @@ -0,0 +1,80 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package verifyreadmes is used to verify that all go modules in the repository +// have a README.md file. +package main + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" +) + +// excludedDirs is a list of directories to exclude from the README check if the full path contains any of these strings. +var excludedDirs = []string{ + "internal", + "test", + "example", + "/.", +} + +const readmeFilename = "README.md" + +// verifyReadme is a [os.WalkFunc] that checks if a README.md exists in the same directory as the go.mod file. +func verifyReadme(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.Mode().IsRegular() || info.Name() != "go.mod" { + return nil + + } + + for _, dir := range excludedDirs { + if strings.Contains(path, dir) { + return nil + } + } + + + // Check that a README.md exists in the same directory as the go.mod file. + readme := filepath.Join(filepath.Dir(path), readmeFilename) + _, err = os.Stat(readme) + if os.IsNotExist(err) { + err = fmt.Errorf("couldn't find %s for %q", readmeFilename, filepath.Dir(path)) + } + + return err +} + +func main() { + root, err := os.Getwd() + if len(os.Args) == 2 { + root, err = filepath.Abs(os.Args[1]) + } + + if err != nil { + fmt.Println("Error: ", err) + os.Exit(1) + } + + fmt.Println("Verifying READMEs in", root) + + var errs []string + filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { + if err := verifyReadme(path, info, err); err != nil { + errs = append(errs, err.Error()) + } + return nil // continue walking + }) + + if len(errs) > 0 { + fmt.Println("Some readme files couldn't be found.") + fmt.Println(strings.Join(errs, "\n")) + os.Exit(1) + } +} diff --git a/verify_readmes.sh b/verify_readmes.sh deleted file mode 100755 index 1e87855ee..000000000 --- a/verify_readmes.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -set -euo pipefail - -dirs=$(find . -type d -not -path "*/internal*" -not -path "*/test*" -not -path "*/example*" -not -path "*/.*" | sort) - -missingReadme=false -for dir in $dirs; do - if [ ! -f "$dir/README.md" ]; then - echo "couldn't find README.md for $dir" - missingReadme=true - fi -done - -if [ "$missingReadme" = true ] ; then - echo "Error: some READMEs couldn't be found." - exit 1 -fi