-
Notifications
You must be signed in to change notification settings - Fork 10
release: v0.8.0 #569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
release: v0.8.0 #569
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a major version upgrade to schema v2, introducing YAML frontmatter support for markdown files and migrating from Go's standard log package to structured logging with slog. The changes enable better metadata management and improve logging consistency across the application.
Key changes:
- Schema migration system enhanced to support incremental migrations with per-version schema file updates
- New frontmatter parsing and generation functionality with robust handling of edge cases
- Migration to structured logging using
slogwith configurable log levels
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/core/tree/frontmatter.go | New file implementing YAML frontmatter parsing, splitting, and building functions with heuristic detection |
| internal/core/tree/frontmatter_test.go | Comprehensive test coverage for frontmatter functionality including edge cases |
| internal/core/tree/tree_service.go | Enhanced migration system, added v2 migration for frontmatter backfill, migrated to slog |
| internal/core/tree/tree_service_test.go | New migration tests and updated existing tests for frontmatter support, translated German comments |
| internal/core/tree/page_store.go | Updated CRUD operations to include frontmatter in all file operations, new ReadPageRaw method |
| internal/core/tree/page_store_test.go | Updated test expectations to account for frontmatter in created files |
| internal/core/tree/schema.go | Bumped CurrentSchemaVersion from 1 to 2 |
| internal/core/tree/errors.go | Added ErrFrontmatterParse and ErrFileNotFound error types |
| cmd/leafwiki/main.go | Added structured logging setup with LOG_LEVEL environment variable support |
| go.mod | Added gopkg.in/yaml.v3 dependency for YAML parsing |
| go.sum | Updated with new yaml.v3 and transitive dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // migrateToV2 migrates the tree to the v2 schema | ||
| // Adds frontmatter to all existing pages if missing |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migrateToV2 function lacks documentation about error handling behavior. Specifically, it's unclear to users what happens when files are missing or when frontmatter parsing fails during migration. Consider adding a detailed function comment that explains the migration process, error handling strategy, and what files are skipped versus which errors cause migration to fail.
| // migrateToV2 migrates the tree to the v2 schema | |
| // Adds frontmatter to all existing pages if missing | |
| // migrateToV2 migrates the tree to the v2 schema. | |
| // | |
| // The migration traverses all pages in the tree and ensures that each page | |
| // has frontmatter. For pages that already have valid frontmatter, the | |
| // existing frontmatter is preserved. For pages without frontmatter, a new | |
| // frontmatter block is added based on the current metadata. | |
| // | |
| // Error handling: | |
| // - If the underlying page file does not exist (os.ErrNotExist or | |
| // ErrFileNotFound), the function logs a warning, skips adding | |
| // frontmatter for that node, but still recurses into and processes | |
| // all of its children. Migration continues for the rest of the tree. | |
| // - If reading the page content fails for any other reason, the error is | |
| // logged and returned, and the migration is aborted. | |
| // - If parsing frontmatter fails for a page, the error is logged and | |
| // returned, and the migration is aborted. | |
| // | |
| // As a result, benign missing-file conditions are tolerated (those nodes are | |
| // skipped), while unexpected I/O or parsing errors cause migrateToV2 to fail. |
internal/core/tree/page_store.go
Outdated
|
|
||
| _, content, _, err := ParseFrontmatter(string(raw)) | ||
| if err != nil { | ||
| return string(raw), err |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ReadPageContent function returns the raw content when frontmatter parsing fails, but still returns the parsing error. This is inconsistent - if parsing fails, the caller gets potentially corrupted data along with an error. Consider either returning an empty string with the error, or logging the error and returning only the body portion that could be extracted.
| return string(raw), err | |
| return "", err |
| t.log.Error("could not build markdown with frontmatter", "nodeID", node.ID, "error", err) | ||
| return fmt.Errorf("could not build markdown with frontmatter for node %s: %w", node.ID, err) |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message uses inconsistent capitalization. The log message starts with lowercase "could not" while error messages in Go conventionally start with lowercase letters, but the fmt.Errorf wrapping should maintain consistency with other error messages in the same function. Consider using "could not build markdown with frontmatter" consistently across both the log and error messages.
internal/core/tree/page_store.go
Outdated
| // Create the file | ||
| content := []byte("# " + newEntry.Title + "\n") | ||
| if err := writeFileAtomic(newFilename, content, 0o644); err != nil { | ||
| fm := Frontmatter{LeafWikiID: newEntry.ID} |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an inconsistency in how frontmatter is created between CreatePage and UpdatePage. CreatePage only sets the LeafWikiID field in frontmatter, while UpdatePage sets both LeafWikiID and LeafWikiTitle. This means pages will have different frontmatter structure depending on whether they were just created or have been updated. Consider making CreatePage also include the title for consistency, or document why this difference exists.
| fm := Frontmatter{LeafWikiID: newEntry.ID} | |
| fm := Frontmatter{LeafWikiID: newEntry.ID, LeafWikiTitle: newEntry.Title} |
internal/core/tree/tree_service.go
Outdated
| fm, body, has, err := ParseFrontmatter(content) | ||
| if err != nil { | ||
| t.log.Error("Could not parse frontmatter for node", "nodeID", node.ID, "error", err) | ||
| return fmt.Errorf("could not parse frontmatter for node %s: %v", node.ID, err) |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When ParseFrontmatter returns an error during migration, the migration immediately fails and stops processing other pages. This could leave the wiki in a partially migrated state where some pages have frontmatter and others don't. Consider logging the error and continuing with the migration for other pages, or at least document this all-or-nothing behavior so users understand that a single corrupted file will prevent migration.
| return fmt.Errorf("could not parse frontmatter for node %s: %v", node.ID, err) | |
| // On parse errors, skip updating this node but continue migrating children | |
| for _, child := range node.Children { | |
| if errChild := addFrontmatter(child); errChild != nil { | |
| t.log.Error("Error adding frontmatter to child node", "nodeID", child.ID, "error", errChild) | |
| } | |
| } | |
| return nil |
internal/core/tree/tree_service.go
Outdated
| if err := writeFileAtomic(filePath, []byte(newContent), 0o644); err != nil { | ||
| t.log.Error("could not write updated page content", "nodeID", node.ID, "filePath", filePath, "error", err) | ||
| return fmt.Errorf("could not write updated page content for node %s: %w", node.ID, err) | ||
| } | ||
|
|
||
| t.log.Info("frontmatter backfilled", "nodeID", node.ID, "path", filePath) | ||
| } |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The migration function writes each file atomically using writeFileAtomic, which is good for data safety. However, for large wikis with many pages, this could be slow as each write involves creating a temporary file and renaming it. Consider adding progress logging to inform users about migration progress, especially since there's already logging for successful frontmatter backfills but no indication of overall progress.
internal/core/tree/page_store.go
Outdated
| fm := Frontmatter{LeafWikiID: entry.ID, LeafWikiTitle: entry.Title} | ||
| contentWithFM, err := BuildMarkdownWithFrontmatter(fm, content) |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UpdatePage function unconditionally overwrites the frontmatter title field with the entry's title from the tree structure. This could overwrite user-provided custom titles in the frontmatter. Consider either preserving the existing frontmatter title when it differs from the tree title, or only updating the ID field while preserving any existing title in the frontmatter.
8de4dcf to
dd36aa0
Compare
117d9d1 to
56c871e
Compare
No description provided.