wip: more progress
This commit is contained in:
parent
f10f5a4403
commit
e6efd71fca
@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"coder.com/coder-registry/cmd/github"
|
"coder.com/coder-registry/cmd/github"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dummyGitDirectory is the directory that a full version of the Registry will
|
// dummyGitDirectory is the directory that a full version of the Registry will
|
||||||
@ -34,7 +35,7 @@ type coderResourceFrontmatter struct {
|
|||||||
// Coder Modules and Coder Templates. If the newReadmeBody and newFrontmatter
|
// Coder Modules and Coder Templates. If the newReadmeBody and newFrontmatter
|
||||||
// fields are nil, that represents that the file has been deleted
|
// fields are nil, that represents that the file has been deleted
|
||||||
type coderResource struct {
|
type coderResource struct {
|
||||||
name string
|
resourceType string
|
||||||
filePath string
|
filePath string
|
||||||
newReadmeBody *string
|
newReadmeBody *string
|
||||||
oldFrontmatter *coderResourceFrontmatter
|
oldFrontmatter *coderResourceFrontmatter
|
||||||
@ -178,10 +179,77 @@ func validateCoderResourceChanges(resource coderResource, actorOrgStatus github.
|
|||||||
return problems
|
return problems
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCoderResourceFiles(oldReadmeFiles []readme, newReadmeFiles []readme, actorOrgStatus github.OrgStatus) (map[string]coderResource, error) {
|
func parseCoderResourceFiles(resourceType string, oldReadmeFiles []readme, newReadmeFiles []readme, actorOrgStatus github.OrgStatus) (map[string]coderResource, error) {
|
||||||
return nil, nil
|
if !slices.Contains(supportedResourceTypes, resourceType) {
|
||||||
|
return nil, fmt.Errorf("resource type %q is not in supported list [%s]", resourceType, strings.Join(supportedResourceTypes, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
resourcesByFilePath := map[string]coderResource{}
|
||||||
|
zipped := zipReadmes(oldReadmeFiles, newReadmeFiles)
|
||||||
|
|
||||||
|
for filePath, z := range zipped {
|
||||||
|
resource := coderResource{
|
||||||
|
resourceType: resourceType,
|
||||||
|
filePath: filePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
if z.new != nil {
|
||||||
|
fm, body, err := separateFrontmatter(z.new.rawText)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
|
||||||
|
} else {
|
||||||
|
resource.newReadmeBody = &body
|
||||||
|
var newFm coderResourceFrontmatter
|
||||||
|
if err := yaml.Unmarshal([]byte(fm), &newFm); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
|
||||||
|
} else {
|
||||||
|
resource.newFrontmatter = &newFm
|
||||||
|
if newFm.Verified != nil && *newFm.Verified {
|
||||||
|
resource.newIsVerified = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if z.old != nil {
|
||||||
|
fm, _, err := separateFrontmatter(z.old.rawText)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
|
||||||
|
} else {
|
||||||
|
var oldFm coderResourceFrontmatter
|
||||||
|
if err := yaml.Unmarshal([]byte(fm), &oldFm); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("resource type %s - %q: %v", resourceType, filePath, err))
|
||||||
|
} else {
|
||||||
|
resource.oldFrontmatter = &oldFm
|
||||||
|
if oldFm.Verified != nil && *oldFm.Verified {
|
||||||
|
resource.oldIsVerified = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if z.old != nil || z.new != nil {
|
||||||
|
resourcesByFilePath[filePath] = resource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range resourcesByFilePath {
|
||||||
|
errs = append(errs, validateCoderResourceChanges(r, actorOrgStatus)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) != 0 {
|
||||||
|
return nil, validationPhaseError{
|
||||||
|
phase: validationPhaseReadmeParsing,
|
||||||
|
errors: errs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resourcesByFilePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Todo: because Coder Resource READMEs will have their full contents
|
||||||
|
// (frontmatter and body) rendered on the Registry site, we need to make sure
|
||||||
|
// that all image references in the body are valid, too
|
||||||
func validateCoderResourceRelativeUrls(map[string]coderResource) []error {
|
func validateCoderResourceRelativeUrls(map[string]coderResource) []error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,9 +13,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"coder.com/coder-registry/cmd/github"
|
"coder.com/coder-registry/cmd/github"
|
||||||
"github.com/go-git/go-git/v5"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -104,53 +101,56 @@ func main() {
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
refactorLater := func() error {
|
moveToOuterScopeLater := func() error {
|
||||||
baseRefReadmeFiles, err := aggregateCoderResourceReadmeFiles("modules")
|
baseRefReadmeFiles, err := aggregateCoderResourceReadmeFiles("modules")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("------ got %d back\n", len(baseRefReadmeFiles))
|
parsed, err := parseCoderResourceFiles("modules", baseRefReadmeFiles, baseRefReadmeFiles, actorOrgStatus)
|
||||||
|
|
||||||
repo, err := git.PlainClone(dummyGitDirectory, true, &git.CloneOptions{
|
|
||||||
URL: "https://github.com/coder/registry",
|
|
||||||
Auth: &http.BasicAuth{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fmt.Printf("------ got %d back\n", len(parsed))
|
||||||
|
|
||||||
head, err := repo.Head()
|
// repo, err := git.PlainClone(dummyGitDirectory, true, &git.CloneOptions{
|
||||||
if err != nil {
|
// URL: "https://github.com/coder/registry",
|
||||||
return err
|
// Auth: &http.BasicAuth{},
|
||||||
}
|
// })
|
||||||
activeBranchName := head.Name().Short()
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
|
||||||
tree, err := repo.Worktree()
|
// head, err := repo.Head()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
err = tree.Checkout(&git.CheckoutOptions{
|
// activeBranchName := head.Name().Short()
|
||||||
Branch: plumbing.NewBranchReferenceName(activeBranchName),
|
|
||||||
Create: false,
|
|
||||||
Force: false,
|
|
||||||
Keep: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Got here!")
|
// tree, err := repo.Worktree()
|
||||||
files, _ := tree.Filesystem.ReadDir(".")
|
// if err != nil {
|
||||||
for _, f := range files {
|
// return err
|
||||||
if f.IsDir() {
|
// }
|
||||||
fmt.Println(f.Name())
|
// err = tree.Checkout(&git.CheckoutOptions{
|
||||||
}
|
// Branch: plumbing.NewBranchReferenceName(activeBranchName),
|
||||||
}
|
// Create: false,
|
||||||
|
// Force: false,
|
||||||
|
// Keep: true,
|
||||||
|
// })
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// files, _ := tree.Filesystem.ReadDir(".")
|
||||||
|
// for _, f := range files {
|
||||||
|
// if f.IsDir() {
|
||||||
|
// fmt.Println(f.Name())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := refactorLater(); err != nil {
|
if err := moveToOuterScopeLater(); err != nil {
|
||||||
errChan <- fmt.Errorf("module validation: %v", err)
|
errChan <- fmt.Errorf("module validation: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -108,3 +108,48 @@ func (p validationPhase) String() string {
|
|||||||
return "Unknown validation phase"
|
return "Unknown validation phase"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type zippedReadmes struct {
|
||||||
|
old *readme
|
||||||
|
new *readme
|
||||||
|
}
|
||||||
|
|
||||||
|
// zipReadmes takes two slices of README files, and combines them into a map,
|
||||||
|
// where each key is a file path, and each value is a struct containing the old
|
||||||
|
// value for the path, and the new value for the path. If the old value exists
|
||||||
|
// but the new one doesn't, that indicates that a file has been deleted. If the
|
||||||
|
// new value exists, but the old one doesn't, that indicates that the file was
|
||||||
|
// created.
|
||||||
|
func zipReadmes(prevReadmes []readme, newReadmes []readme) map[string]zippedReadmes {
|
||||||
|
oldMap := map[string]readme{}
|
||||||
|
for _, rm := range prevReadmes {
|
||||||
|
oldMap[rm.filePath] = rm
|
||||||
|
}
|
||||||
|
|
||||||
|
zipped := map[string]zippedReadmes{}
|
||||||
|
for _, rm := range newReadmes {
|
||||||
|
old, ok := oldMap[rm.filePath]
|
||||||
|
if ok {
|
||||||
|
zipped[rm.filePath] = zippedReadmes{
|
||||||
|
old: &old,
|
||||||
|
new: &rm,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
zipped[rm.filePath] = zippedReadmes{
|
||||||
|
old: nil,
|
||||||
|
new: &rm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, old := range oldMap {
|
||||||
|
_, ok := zipped[old.filePath]
|
||||||
|
if !ok {
|
||||||
|
zipped[old.filePath] = zippedReadmes{
|
||||||
|
old: &old,
|
||||||
|
new: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zipped
|
||||||
|
}
|
||||||
|
|||||||
@ -37,10 +37,7 @@ func validateCoderResourceSubdirectory(dirPath string) []error {
|
|||||||
|
|
||||||
resourceReadmePath := path.Join(dirPath, f.Name(), "README.md")
|
resourceReadmePath := path.Join(dirPath, f.Name(), "README.md")
|
||||||
_, err := os.Stat(resourceReadmePath)
|
_, err := os.Stat(resourceReadmePath)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
errs = append(errs, fmt.Errorf("%q: README file does not exist", resourceReadmePath))
|
errs = append(errs, fmt.Errorf("%q: README file does not exist", resourceReadmePath))
|
||||||
} else {
|
} else {
|
||||||
@ -48,6 +45,18 @@ func validateCoderResourceSubdirectory(dirPath string) []error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainTerraformPath := path.Join(dirPath, f.Name(), "main.tf")
|
||||||
|
_, err = os.Stat(mainTerraformPath)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
errs = append(errs, fmt.Errorf("%q: 'main.tf' file does not exist", mainTerraformPath))
|
||||||
|
} else {
|
||||||
|
errs = append(errs, addFilePathToError(mainTerraformPath, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +80,6 @@ func validateRegistryDirectory() []error {
|
|||||||
problems = append(problems, err)
|
problems = append(problems, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mainTerraformPath := path.Join(dirPath, "main.tf")
|
|
||||||
_, err = os.Stat(mainTerraformPath)
|
|
||||||
if err != nil {
|
|
||||||
problems = append(problems, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rType := range supportedResourceTypes {
|
for _, rType := range supportedResourceTypes {
|
||||||
resourcePath := path.Join(dirPath, rType)
|
resourcePath := path.Join(dirPath, rType)
|
||||||
if errs := validateCoderResourceSubdirectory(resourcePath); len(errs) != 0 {
|
if errs := validateCoderResourceSubdirectory(resourcePath); len(errs) != 0 {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user