Root causes of the remaining 5 CI PG failures (and the hidden flaky set):
1. All PG-integration packages shared ONE database under parallel package
execution - migrations/seeds/truncates raced (nondeterministic failure
sets, locally and in CI).
Fix: RequireTestDatabaseURL/SkipIfNoTestDatabaseURL now derive a
per-package database (<base>_<pkgHash>, advisory-lock-guarded
CREATE); 9 raw-env straggler tests funnelled through the helpers;
db-package tests call it unqualified (no import cycle).
2. Approval-chain fixtures were not production-shaped: freezeReviewSnapshot
only honors head_snapshot_id, fake content hashes never froze a
snapshot, so ApproverApprove rejected with 'approved requires frozen
review_snapshot_id'. Errors were swallowed (_, _ =) hiding this.
Fix (ownership-respecting, arch-enforced):
- docrevision.SeedContentSnapshotForTest seeds the ledger tables it owns
- docgov GovernanceEngine.FreezeHeadSnapshotForTest freezes head/review
pointers on document_records (docgov-owned) and clears engine cache
- all four integration fixtures use the pair; swallowed errors checked
3. Fixed-name fixtures collide once a package shares one DB (projects
uq_projects_name_global): uniquified in projectinstance + server tests.
4. CAS/ctxmgr tests never bootstrapped migrations (relied on other packages
having migrated the shared DB): explicit RunMigrationsOnceForTest.
Verified: full parallel short suite = 75 packages, 0 failures against an
isolated throwaway PG. CI skip list removed - short tests fully required.
38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
package docrevision
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/jackc/pgx/v5/pgxpool"
|
||
)
|
||
|
||
// SeedContentSnapshotForTest 以生产同构方式写入内容快照(本模块所有的
|
||
// document_content_blobs + document_snapshots)并返回快照 ID。
|
||
//
|
||
// 用途:集成测试构造合法的 送审→审核→批准 链——账本封快照正是本模块的
|
||
// 生产行为。document_records 上的 head/review 指针回填归 docgov
|
||
//(GovernanceEngine.FreezeHeadSnapshotForTest),两者配合使用。
|
||
func SeedContentSnapshotForTest(ctx context.Context, pool *pgxpool.Pool, docID string, actorID int64, content string) (int64, error) {
|
||
if pool == nil {
|
||
return 0, fmt.Errorf("docrevision: SeedContentSnapshotForTest requires a pool")
|
||
}
|
||
sha := fmt.Sprintf("sha_seed_%d", time.Now().UnixNano())
|
||
var snapID int64
|
||
err := pool.QueryRow(ctx, `
|
||
WITH blob AS (
|
||
INSERT INTO document_content_blobs (content_sha256, content_markdown, byte_size, created_at)
|
||
VALUES ($2, $3, $4, now())
|
||
RETURNING content_sha256
|
||
)
|
||
INSERT INTO document_snapshots (doc_id, content_sha256, actor_user_id, actor_snapshot, source_kind, created_at)
|
||
SELECT $1::text, blob.content_sha256, $5, '[]'::jsonb, 'human', now() FROM blob
|
||
RETURNING id
|
||
`, docID, sha, content, len(content), actorID).Scan(&snapID)
|
||
if err != nil {
|
||
return 0, fmt.Errorf("docrevision: seed snapshot: %w", err)
|
||
}
|
||
return snapID, nil
|
||
}
|