WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
"github.com/Tencent/WeKnora/internal/types/interfaces"
|
||||
)
|
||||
|
||||
type wikiContentRewrite func(string) (string, bool)
|
||||
|
||||
type appliedWikiContentChange struct {
|
||||
page *types.WikiPage
|
||||
originalContent string
|
||||
}
|
||||
|
||||
// applyIncomingWikiContentRewrite updates machine-maintained links without
|
||||
// incrementing user-visible page versions. It stops on the first failure and
|
||||
// returns the already-applied changes so the caller can compensate.
|
||||
func applyIncomingWikiContentRewrite(
|
||||
ctx context.Context,
|
||||
service interfaces.WikiPageService,
|
||||
kbID string,
|
||||
inLinks []string,
|
||||
rewrite wikiContentRewrite,
|
||||
) ([]appliedWikiContentChange, []string, error) {
|
||||
var changes []appliedWikiContentChange
|
||||
var updatedSlugs []string
|
||||
for _, sourceSlug := range dedupNonEmptyStrings(inLinks) {
|
||||
page, err := service.GetPageBySlug(ctx, kbID, sourceSlug)
|
||||
if err != nil || page == nil {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("empty result")
|
||||
}
|
||||
return changes, updatedSlugs, fmt.Errorf("load incoming page %s: %w", sourceSlug, err)
|
||||
}
|
||||
updatedContent, changed := rewrite(page.Content)
|
||||
if !changed {
|
||||
continue
|
||||
}
|
||||
original := page.Content
|
||||
page.Content = updatedContent
|
||||
if err := service.UpdateAutoLinkedContent(ctx, page); err != nil {
|
||||
page.Content = original
|
||||
return changes, updatedSlugs, fmt.Errorf("update incoming page %s: %w", sourceSlug, err)
|
||||
}
|
||||
changes = append(changes, appliedWikiContentChange{page: page, originalContent: original})
|
||||
updatedSlugs = append(updatedSlugs, sourceSlug)
|
||||
}
|
||||
return changes, updatedSlugs, nil
|
||||
}
|
||||
|
||||
func rollbackWikiContentChanges(
|
||||
ctx context.Context,
|
||||
service interfaces.WikiPageService,
|
||||
changes []appliedWikiContentChange,
|
||||
) error {
|
||||
var failures []string
|
||||
for i := len(changes) - 1; i >= 0; i-- {
|
||||
change := changes[i]
|
||||
change.page.Content = change.originalContent
|
||||
if err := service.UpdateAutoLinkedContent(ctx, change.page); err != nil {
|
||||
failures = append(failures, fmt.Sprintf("%s: %v", change.page.Slug, err))
|
||||
}
|
||||
}
|
||||
if len(failures) > 0 {
|
||||
return fmt.Errorf("failed to roll back incoming pages: %s", strings.Join(failures, "; "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func joinWikiMutationErrors(primary error, extras ...error) string {
|
||||
parts := []string{primary.Error()}
|
||||
for _, err := range extras {
|
||||
if err != nil {
|
||||
parts = append(parts, err.Error())
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, "; ")
|
||||
}
|
||||
Reference in New Issue
Block a user