forked from tangled.org/core
Monorepo for Tangled

appview: make default label defs configurable

hard-coded labels make hard to setup local sandboxed environment as the
appview won't run until we fill all 5 definitions under TangledDid.

so make them configurable with `TANGLED_LABEL_DEFAULTS` which is a list
of aturis delimitted by , character

we can have any number/kind of default labels but gfi is required for
`/good-first-issue` page

Signed-off-by: Seongmin Lee <git@boltless.me>

authored by boltless.me and committed by Tangled cab269fb 41091062

Changed files
+39 -54
appview
config
models
repo
state
+6
appview/config/config.go
··· 80 80 TurnstileSecretKey string `env:"TURNSTILE_SECRET_KEY"` 81 81 } 82 82 83 + type LabelConfig struct { 84 + DefaultLabelDefs []string `env:"DEFAULTS, default=at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/wontfix,at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/good-first-issue,at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/duplicate,at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/documentation,at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/assignee"` // delimiter=, 85 + GoodFirstIssue string `env:"GFI, default=at://did:plc:wshs7t2adsemcrrd4snkeqli/sh.tangled.label.definition/good-first-issue"` 86 + } 87 + 83 88 func (cfg RedisConfig) ToURL() string { 84 89 u := &url.URL{ 85 90 Scheme: "redis", ··· 107 112 Redis RedisConfig `env:",prefix=TANGLED_REDIS_"` 108 113 Pds PdsConfig `env:",prefix=TANGLED_PDS_"` 109 114 Cloudflare Cloudflare `env:",prefix=TANGLED_CLOUDFLARE_"` 115 + Label LabelConfig `env:",prefix=TANGLED_LABEL_"` 110 116 } 111 117 112 118 func LoadConfig(ctx context.Context) (*Config, error) {
+25 -43
appview/models/label.go
··· 14 14 "github.com/bluesky-social/indigo/atproto/syntax" 15 15 "github.com/bluesky-social/indigo/xrpc" 16 16 "tangled.org/core/api/tangled" 17 - "tangled.org/core/consts" 18 17 "tangled.org/core/idresolver" 19 18 ) 20 19 ··· 461 460 return result 462 461 } 463 462 464 - var ( 465 - LabelWontfix = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "wontfix") 466 - LabelDuplicate = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "duplicate") 467 - LabelAssignee = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "assignee") 468 - LabelGoodFirstIssue = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "good-first-issue") 469 - LabelDocumentation = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "documentation") 470 - ) 463 + func FetchLabelDefs(r *idresolver.Resolver, aturis []string) ([]LabelDefinition, error) { 464 + var labelDefs []LabelDefinition 465 + ctx := context.Background() 471 466 472 - func DefaultLabelDefs() []string { 473 - return []string{ 474 - LabelWontfix, 475 - LabelDuplicate, 476 - LabelAssignee, 477 - LabelGoodFirstIssue, 478 - LabelDocumentation, 479 - } 480 - } 467 + for _, dl := range aturis { 468 + atUri, err := syntax.ParseATURI(dl) 469 + if err != nil { 470 + return nil, fmt.Errorf("failed to parse AT-URI %s: %v", dl, err) 471 + } 472 + if atUri.Collection() != tangled.LabelDefinitionNSID { 473 + return nil, fmt.Errorf("expected AT-URI pointing %s collection: %s", tangled.LabelDefinitionNSID, atUri) 474 + } 481 475 482 - func FetchDefaultDefs(r *idresolver.Resolver) ([]LabelDefinition, error) { 483 - resolved, err := r.ResolveIdent(context.Background(), consts.TangledDid) 484 - if err != nil { 485 - return nil, fmt.Errorf("failed to resolve tangled.sh DID %s: %v", consts.TangledDid, err) 486 - } 487 - pdsEndpoint := resolved.PDSEndpoint() 488 - if pdsEndpoint == "" { 489 - return nil, fmt.Errorf("no PDS endpoint found for tangled.sh DID %s", consts.TangledDid) 490 - } 491 - client := &xrpc.Client{ 492 - Host: pdsEndpoint, 493 - } 476 + owner, err := r.ResolveIdent(ctx, atUri.Authority().String()) 477 + if err != nil { 478 + return nil, fmt.Errorf("failed to resolve default label owner DID %s: %v", atUri.Authority(), err) 479 + } 494 480 495 - var labelDefs []LabelDefinition 481 + xrpcc := xrpc.Client{ 482 + Host: owner.PDSEndpoint(), 483 + } 496 484 497 - for _, dl := range DefaultLabelDefs() { 498 - atUri := syntax.ATURI(dl) 499 - parsedUri, err := syntax.ParseATURI(string(atUri)) 500 - if err != nil { 501 - return nil, fmt.Errorf("failed to parse AT-URI %s: %v", atUri, err) 502 - } 503 485 record, err := atproto.RepoGetRecord( 504 - context.Background(), 505 - client, 486 + ctx, 487 + &xrpcc, 506 488 "", 507 - parsedUri.Collection().String(), 508 - parsedUri.Authority().String(), 509 - parsedUri.RecordKey().String(), 489 + atUri.Collection().String(), 490 + atUri.Authority().String(), 491 + atUri.RecordKey().String(), 510 492 ) 511 493 if err != nil { 512 494 return nil, fmt.Errorf("failed to get record for %s: %v", atUri, err) ··· 526 508 } 527 509 528 510 labelDef, err := LabelDefinitionFromRecord( 529 - parsedUri.Authority().String(), 530 - parsedUri.RecordKey().String(), 511 + atUri.Authority().String(), 512 + atUri.RecordKey().String(), 531 513 labelRecord, 532 514 ) 533 515 if err != nil {
+2 -2
appview/repo/repo.go
··· 1968 1968 return 1969 1969 } 1970 1970 1971 - defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", models.DefaultLabelDefs())) 1971 + defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", rp.config.Label.DefaultLabelDefs)) 1972 1972 if err != nil { 1973 1973 l.Error("failed to fetch labels", "err", err) 1974 1974 rp.pages.Error503(w) ··· 2247 2247 Source: sourceAt, 2248 2248 Description: f.Repo.Description, 2249 2249 Created: time.Now(), 2250 - Labels: models.DefaultLabelDefs(), 2250 + Labels: rp.config.Label.DefaultLabelDefs, 2251 2251 } 2252 2252 record := repo.AsRecord() 2253 2253
+1 -3
appview/state/gfi.go
··· 1 1 package state 2 2 3 3 import ( 4 - "fmt" 5 4 "log" 6 5 "net/http" 7 6 "sort" 8 7 9 8 "github.com/bluesky-social/indigo/atproto/syntax" 10 - "tangled.org/core/api/tangled" 11 9 "tangled.org/core/appview/db" 12 10 "tangled.org/core/appview/models" 13 11 "tangled.org/core/appview/pages" ··· 20 18 21 19 page := pagination.FromContext(r.Context()) 22 20 23 - goodFirstIssueLabel := fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "good-first-issue") 21 + goodFirstIssueLabel := s.config.Label.GoodFirstIssue 24 22 25 23 gfiLabelDef, err := db.GetLabelDefinition(s.db, db.FilterEq("at_uri", goodFirstIssueLabel)) 26 24 if err != nil {
+5 -6
appview/state/state.go
··· 129 129 return nil, fmt.Errorf("failed to create jetstream client: %w", err) 130 130 } 131 131 132 - if err := BackfillDefaultDefs(d, res); err != nil { 132 + if err := BackfillDefaultDefs(d, res, config.Label.DefaultLabelDefs); err != nil { 133 133 return nil, fmt.Errorf("failed to backfill default label defs: %w", err) 134 134 } 135 135 ··· 294 294 return 295 295 } 296 296 297 - gfiLabel, err := db.GetLabelDefinition(s.db, db.FilterEq("at_uri", models.LabelGoodFirstIssue)) 297 + gfiLabel, err := db.GetLabelDefinition(s.db, db.FilterEq("at_uri", s.config.Label.GoodFirstIssue)) 298 298 if err != nil { 299 299 // non-fatal 300 300 } ··· 517 517 Rkey: rkey, 518 518 Description: description, 519 519 Created: time.Now(), 520 - Labels: models.DefaultLabelDefs(), 520 + Labels: s.config.Label.DefaultLabelDefs, 521 521 } 522 522 record := repo.AsRecord() 523 523 ··· 659 659 return err 660 660 } 661 661 662 - func BackfillDefaultDefs(e db.Execer, r *idresolver.Resolver) error { 663 - defaults := models.DefaultLabelDefs() 662 + func BackfillDefaultDefs(e db.Execer, r *idresolver.Resolver, defaults []string) error { 664 663 defaultLabels, err := db.GetLabelDefinitions(e, db.FilterIn("at_uri", defaults)) 665 664 if err != nil { 666 665 return err ··· 670 669 return nil 671 670 } 672 671 673 - labelDefs, err := models.FetchDefaultDefs(r) 672 + labelDefs, err := models.FetchLabelDefs(r, defaults) 674 673 if err != nil { 675 674 return err 676 675 }