Signed-off-by: nelind nel.n.lindberg@gmail.com
+202
-1
api/tangled/cbor_gen.go
+202
-1
api/tangled/cbor_gen.go
···
6392
6393
return nil
6394
}
6395
func (t *RepoPull_Target) MarshalCBOR(w io.Writer) error {
6396
if t == nil {
6397
_, err := w.Write(cbg.CborNull)
···
6533
}
6534
6535
cw := cbg.NewCborWriter(w)
6536
-
fieldCount := 7
6537
6538
if t.Body == nil {
6539
fieldCount--
···
6543
fieldCount--
6544
}
6545
6546
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
6547
return err
6548
}
···
6701
if _, err := cw.WriteString(string(t.CreatedAt)); err != nil {
6702
return err
6703
}
6704
return nil
6705
}
6706
···
6850
6851
t.CreatedAt = string(sval)
6852
}
6853
6854
default:
6855
// Field doesn't exist on this type, so ignore it
···
6392
6393
return nil
6394
}
6395
+
func (t *RepoPull_StackInfo) MarshalCBOR(w io.Writer) error {
6396
+
if t == nil {
6397
+
_, err := w.Write(cbg.CborNull)
6398
+
return err
6399
+
}
6400
+
6401
+
cw := cbg.NewCborWriter(w)
6402
+
fieldCount := 2
6403
+
6404
+
if t.Parent == nil {
6405
+
fieldCount--
6406
+
}
6407
+
6408
+
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
6409
+
return err
6410
+
}
6411
+
6412
+
// t.Parent (string) (string)
6413
+
if t.Parent != nil {
6414
+
6415
+
if len("parent") > 1000000 {
6416
+
return xerrors.Errorf("Value in field \"parent\" was too long")
6417
+
}
6418
+
6419
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("parent"))); err != nil {
6420
+
return err
6421
+
}
6422
+
if _, err := cw.WriteString(string("parent")); err != nil {
6423
+
return err
6424
+
}
6425
+
6426
+
if t.Parent == nil {
6427
+
if _, err := cw.Write(cbg.CborNull); err != nil {
6428
+
return err
6429
+
}
6430
+
} else {
6431
+
if len(*t.Parent) > 1000000 {
6432
+
return xerrors.Errorf("Value in field t.Parent was too long")
6433
+
}
6434
+
6435
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(*t.Parent))); err != nil {
6436
+
return err
6437
+
}
6438
+
if _, err := cw.WriteString(string(*t.Parent)); err != nil {
6439
+
return err
6440
+
}
6441
+
}
6442
+
}
6443
+
6444
+
// t.ChangeId (string) (string)
6445
+
if len("changeId") > 1000000 {
6446
+
return xerrors.Errorf("Value in field \"changeId\" was too long")
6447
+
}
6448
+
6449
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("changeId"))); err != nil {
6450
+
return err
6451
+
}
6452
+
if _, err := cw.WriteString(string("changeId")); err != nil {
6453
+
return err
6454
+
}
6455
+
6456
+
if len(t.ChangeId) > 1000000 {
6457
+
return xerrors.Errorf("Value in field t.ChangeId was too long")
6458
+
}
6459
+
6460
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.ChangeId))); err != nil {
6461
+
return err
6462
+
}
6463
+
if _, err := cw.WriteString(string(t.ChangeId)); err != nil {
6464
+
return err
6465
+
}
6466
+
return nil
6467
+
}
6468
+
6469
+
func (t *RepoPull_StackInfo) UnmarshalCBOR(r io.Reader) (err error) {
6470
+
*t = RepoPull_StackInfo{}
6471
+
6472
+
cr := cbg.NewCborReader(r)
6473
+
6474
+
maj, extra, err := cr.ReadHeader()
6475
+
if err != nil {
6476
+
return err
6477
+
}
6478
+
defer func() {
6479
+
if err == io.EOF {
6480
+
err = io.ErrUnexpectedEOF
6481
+
}
6482
+
}()
6483
+
6484
+
if maj != cbg.MajMap {
6485
+
return fmt.Errorf("cbor input should be of type map")
6486
+
}
6487
+
6488
+
if extra > cbg.MaxLength {
6489
+
return fmt.Errorf("RepoPull_StackInfo: map struct too large (%d)", extra)
6490
+
}
6491
+
6492
+
n := extra
6493
+
6494
+
nameBuf := make([]byte, 8)
6495
+
for i := uint64(0); i < n; i++ {
6496
+
nameLen, ok, err := cbg.ReadFullStringIntoBuf(cr, nameBuf, 1000000)
6497
+
if err != nil {
6498
+
return err
6499
+
}
6500
+
6501
+
if !ok {
6502
+
// Field doesn't exist on this type, so ignore it
6503
+
if err := cbg.ScanForLinks(cr, func(cid.Cid) {}); err != nil {
6504
+
return err
6505
+
}
6506
+
continue
6507
+
}
6508
+
6509
+
switch string(nameBuf[:nameLen]) {
6510
+
// t.Parent (string) (string)
6511
+
case "parent":
6512
+
6513
+
{
6514
+
b, err := cr.ReadByte()
6515
+
if err != nil {
6516
+
return err
6517
+
}
6518
+
if b != cbg.CborNull[0] {
6519
+
if err := cr.UnreadByte(); err != nil {
6520
+
return err
6521
+
}
6522
+
6523
+
sval, err := cbg.ReadStringWithMax(cr, 1000000)
6524
+
if err != nil {
6525
+
return err
6526
+
}
6527
+
6528
+
t.Parent = (*string)(&sval)
6529
+
}
6530
+
}
6531
+
// t.ChangeId (string) (string)
6532
+
case "changeId":
6533
+
6534
+
{
6535
+
sval, err := cbg.ReadStringWithMax(cr, 1000000)
6536
+
if err != nil {
6537
+
return err
6538
+
}
6539
+
6540
+
t.ChangeId = string(sval)
6541
+
}
6542
+
6543
+
default:
6544
+
// Field doesn't exist on this type, so ignore it
6545
+
if err := cbg.ScanForLinks(r, func(cid.Cid) {}); err != nil {
6546
+
return err
6547
+
}
6548
+
}
6549
+
}
6550
+
6551
+
return nil
6552
+
}
6553
func (t *RepoPull_Target) MarshalCBOR(w io.Writer) error {
6554
if t == nil {
6555
_, err := w.Write(cbg.CborNull)
···
6691
}
6692
6693
cw := cbg.NewCborWriter(w)
6694
+
fieldCount := 8
6695
6696
if t.Body == nil {
6697
fieldCount--
···
6701
fieldCount--
6702
}
6703
6704
+
if t.StackInfo == nil {
6705
+
fieldCount--
6706
+
}
6707
+
6708
if _, err := cw.Write(cbg.CborEncodeMajorType(cbg.MajMap, uint64(fieldCount))); err != nil {
6709
return err
6710
}
···
6863
if _, err := cw.WriteString(string(t.CreatedAt)); err != nil {
6864
return err
6865
}
6866
+
6867
+
// t.StackInfo (tangled.RepoPull_StackInfo) (struct)
6868
+
if t.StackInfo != nil {
6869
+
6870
+
if len("stackInfo") > 1000000 {
6871
+
return xerrors.Errorf("Value in field \"stackInfo\" was too long")
6872
+
}
6873
+
6874
+
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("stackInfo"))); err != nil {
6875
+
return err
6876
+
}
6877
+
if _, err := cw.WriteString(string("stackInfo")); err != nil {
6878
+
return err
6879
+
}
6880
+
6881
+
if err := t.StackInfo.MarshalCBOR(cw); err != nil {
6882
+
return err
6883
+
}
6884
+
}
6885
return nil
6886
}
6887
···
7031
7032
t.CreatedAt = string(sval)
7033
}
7034
+
// t.StackInfo (tangled.RepoPull_StackInfo) (struct)
7035
+
case "stackInfo":
7036
+
7037
+
{
7038
+
7039
+
b, err := cr.ReadByte()
7040
+
if err != nil {
7041
+
return err
7042
+
}
7043
+
if b != cbg.CborNull[0] {
7044
+
if err := cr.UnreadByte(); err != nil {
7045
+
return err
7046
+
}
7047
+
t.StackInfo = new(RepoPull_StackInfo)
7048
+
if err := t.StackInfo.UnmarshalCBOR(cr); err != nil {
7049
+
return xerrors.Errorf("unmarshaling t.StackInfo pointer: %w", err)
7050
+
}
7051
+
}
7052
+
7053
+
}
7054
7055
default:
7056
// Field doesn't exist on this type, so ignore it
+16
-7
api/tangled/repopull.go
+16
-7
api/tangled/repopull.go
···
17
} //
18
// RECORDTYPE: RepoPull
19
type RepoPull struct {
20
-
LexiconTypeID string `json:"$type,const=sh.tangled.repo.pull" cborgen:"$type,const=sh.tangled.repo.pull"`
21
-
Body *string `json:"body,omitempty" cborgen:"body,omitempty"`
22
-
CreatedAt string `json:"createdAt" cborgen:"createdAt"`
23
-
Patch string `json:"patch" cborgen:"patch"`
24
-
Source *RepoPull_Source `json:"source,omitempty" cborgen:"source,omitempty"`
25
-
Target *RepoPull_Target `json:"target" cborgen:"target"`
26
-
Title string `json:"title" cborgen:"title"`
27
}
28
29
// RepoPull_Source is a "source" in the sh.tangled.repo.pull schema.
···
33
Sha string `json:"sha" cborgen:"sha"`
34
}
35
36
// RepoPull_Target is a "target" in the sh.tangled.repo.pull schema.
37
type RepoPull_Target struct {
38
Branch string `json:"branch" cborgen:"branch"`
···
17
} //
18
// RECORDTYPE: RepoPull
19
type RepoPull struct {
20
+
LexiconTypeID string `json:"$type,const=sh.tangled.repo.pull" cborgen:"$type,const=sh.tangled.repo.pull"`
21
+
Body *string `json:"body,omitempty" cborgen:"body,omitempty"`
22
+
CreatedAt string `json:"createdAt" cborgen:"createdAt"`
23
+
Patch string `json:"patch" cborgen:"patch"`
24
+
Source *RepoPull_Source `json:"source,omitempty" cborgen:"source,omitempty"`
25
+
StackInfo *RepoPull_StackInfo `json:"stackInfo,omitempty" cborgen:"stackInfo,omitempty"`
26
+
Target *RepoPull_Target `json:"target" cborgen:"target"`
27
+
Title string `json:"title" cborgen:"title"`
28
}
29
30
// RepoPull_Source is a "source" in the sh.tangled.repo.pull schema.
···
34
Sha string `json:"sha" cborgen:"sha"`
35
}
36
37
+
// RepoPull_StackInfo is a "stackInfo" in the sh.tangled.repo.pull schema.
38
+
type RepoPull_StackInfo struct {
39
+
// changeId: Change ID of this commit/change. Principly also available in the patch itself as a line in the commit footer.
40
+
ChangeId string `json:"changeId" cborgen:"changeId"`
41
+
// parent: AT-URI of the PR for the parent commit/change in the change stack.
42
+
Parent *string `json:"parent,omitempty" cborgen:"parent,omitempty"`
43
+
}
44
+
45
// RepoPull_Target is a "target" in the sh.tangled.repo.pull schema.
46
type RepoPull_Target struct {
47
Branch string `json:"branch" cborgen:"branch"`
+7
appview/db/db.go
+7
appview/db/db.go
+37
-10
appview/db/pulls.go
+37
-10
appview/db/pulls.go
···
72
// stacking
73
StackId string // nullable string
74
ChangeId string // nullable string
75
ParentChangeId string // nullable string
76
77
// meta
···
91
}
92
93
record := tangled.RepoPull{
94
-
Title: p.Title,
95
-
Body: &p.Body,
96
-
CreatedAt: p.Created.Format(time.RFC3339),
97
Target: &tangled.RepoPull_Target{
98
Repo: p.RepoAt.String(),
99
Branch: p.TargetBranch,
100
},
101
-
Patch: p.LatestPatch(),
102
-
Source: source,
103
}
104
return record
105
}
···
255
}
256
}
257
258
-
var stackId, changeId, parentChangeId *string
259
if pull.StackId != "" {
260
stackId = &pull.StackId
261
}
262
if pull.ChangeId != "" {
263
changeId = &pull.ChangeId
264
}
265
if pull.ParentChangeId != "" {
266
parentChangeId = &pull.ParentChangeId
267
}
···
269
_, err = tx.Exec(
270
`
271
insert into pulls (
272
-
repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_change_id
273
)
274
-
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
275
pull.RepoAt,
276
pull.OwnerDid,
277
pull.PullId,
···
284
sourceRepoAt,
285
stackId,
286
changeId,
287
parentChangeId,
288
)
289
if err != nil {
···
345
source_repo_at,
346
stack_id,
347
change_id,
348
parent_change_id
349
from
350
pulls
···
363
for rows.Next() {
364
var pull Pull
365
var createdAt string
366
-
var sourceBranch, sourceRepoAt, stackId, changeId, parentChangeId sql.NullString
367
err := rows.Scan(
368
&pull.OwnerDid,
369
&pull.RepoAt,
···
378
&sourceRepoAt,
379
&stackId,
380
&changeId,
381
&parentChangeId,
382
)
383
if err != nil {
···
409
if changeId.Valid {
410
pull.ChangeId = changeId.String
411
}
412
if parentChangeId.Valid {
413
pull.ParentChangeId = parentChangeId.String
414
}
···
549
source_repo_at,
550
stack_id,
551
change_id,
552
parent_change_id
553
from
554
pulls
···
559
560
var pull Pull
561
var createdAt string
562
-
var sourceBranch, sourceRepoAt, stackId, changeId, parentChangeId sql.NullString
563
err := row.Scan(
564
&pull.OwnerDid,
565
&pull.PullId,
···
574
&sourceRepoAt,
575
&stackId,
576
&changeId,
577
&parentChangeId,
578
)
579
if err != nil {
···
606
if changeId.Valid {
607
pull.ChangeId = changeId.String
608
}
609
if parentChangeId.Valid {
610
pull.ParentChangeId = parentChangeId.String
611
}
···
72
// stacking
73
StackId string // nullable string
74
ChangeId string // nullable string
75
+
ParentAt *syntax.ATURI
76
ParentChangeId string // nullable string
77
78
// meta
···
92
}
93
94
record := tangled.RepoPull{
95
+
Title: p.Title,
96
+
Body: &p.Body,
97
+
CreatedAt: p.Created.Format(time.RFC3339),
98
Target: &tangled.RepoPull_Target{
99
Repo: p.RepoAt.String(),
100
Branch: p.TargetBranch,
101
},
102
+
Patch: p.LatestPatch(),
103
+
Source: source,
104
+
StackInfo: &tangled.RepoPull_StackInfo{
105
+
ChangeId: p.ChangeId,
106
+
Parent: (*string)(p.ParentAt),
107
+
},
108
}
109
return record
110
}
···
260
}
261
}
262
263
+
var stackId, changeId, parentAt, parentChangeId *string
264
if pull.StackId != "" {
265
stackId = &pull.StackId
266
}
267
if pull.ChangeId != "" {
268
changeId = &pull.ChangeId
269
}
270
+
if pull.ParentAt != nil {
271
+
parentAt = (*string)(pull.ParentAt)
272
+
}
273
if pull.ParentChangeId != "" {
274
parentChangeId = &pull.ParentChangeId
275
}
···
277
_, err = tx.Exec(
278
`
279
insert into pulls (
280
+
repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_at, parent_change_id
281
)
282
+
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
283
pull.RepoAt,
284
pull.OwnerDid,
285
pull.PullId,
···
292
sourceRepoAt,
293
stackId,
294
changeId,
295
+
parentAt,
296
parentChangeId,
297
)
298
if err != nil {
···
354
source_repo_at,
355
stack_id,
356
change_id,
357
+
parent_at,
358
parent_change_id
359
from
360
pulls
···
373
for rows.Next() {
374
var pull Pull
375
var createdAt string
376
+
var sourceBranch, sourceRepoAt, stackId, changeId, parentAt, parentChangeId sql.NullString
377
err := rows.Scan(
378
&pull.OwnerDid,
379
&pull.RepoAt,
···
388
&sourceRepoAt,
389
&stackId,
390
&changeId,
391
+
&parentAt,
392
&parentChangeId,
393
)
394
if err != nil {
···
420
if changeId.Valid {
421
pull.ChangeId = changeId.String
422
}
423
+
if parentAt.Valid {
424
+
parentAtParsed, err := syntax.ParseATURI(parentAt.String)
425
+
if err != nil {
426
+
return nil, err
427
+
}
428
+
pull.ParentAt = &parentAtParsed
429
+
}
430
if parentChangeId.Valid {
431
pull.ParentChangeId = parentChangeId.String
432
}
···
567
source_repo_at,
568
stack_id,
569
change_id,
570
+
parent_at,
571
parent_change_id
572
from
573
pulls
···
578
579
var pull Pull
580
var createdAt string
581
+
var sourceBranch, sourceRepoAt, stackId, changeId, parentAt, parentChangeId sql.NullString
582
err := row.Scan(
583
&pull.OwnerDid,
584
&pull.PullId,
···
593
&sourceRepoAt,
594
&stackId,
595
&changeId,
596
+
&parentAt,
597
&parentChangeId,
598
)
599
if err != nil {
···
626
if changeId.Valid {
627
pull.ChangeId = changeId.String
628
}
629
+
if parentAt.Valid {
630
+
parsedParentAt, err := syntax.ParseATURI(parentAt.String)
631
+
if err != nil {
632
+
return nil, err
633
+
}
634
+
pull.ParentAt = &parsedParentAt
635
+
}
636
if parentChangeId.Valid {
637
pull.ParentChangeId = parentChangeId.String
638
}
+22
-2
appview/pulls/pulls.go
+22
-2
appview/pulls/pulls.go
···
29
30
"github.com/bluekeyes/go-gitdiff/gitdiff"
31
comatproto "github.com/bluesky-social/indigo/api/atproto"
32
lexutil "github.com/bluesky-social/indigo/lex/util"
33
"github.com/go-chi/chi/v5"
34
"github.com/google/uuid"
···
1633
newStack, err := newStack(f, user, targetBranch, patch, pull.PullSource, stackId)
1634
if err != nil {
1635
log.Println("failed to create resubmitted stack", err)
1636
-
s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
1637
return
1638
}
1639
1640
// find the diff between the stacks, first, map them by changeId
1641
origById := make(map[string]*db.Pull)
1642
newById := make(map[string]*db.Pull)
1643
for _, p := range origStack {
1644
origById[p.ChangeId] = p
1645
}
1646
for _, p := range newStack {
1647
newById[p.ChangeId] = p
1648
}
1649
···
1691
// we still need to update the hash in submission.Patch and submission.SourceRev
1692
if patchutil.Equal(newFiles, origFiles) &&
1693
origHeader.Title == newHeader.Title &&
1694
-
origHeader.Body == newHeader.Body {
1695
unchanged[op.ChangeId] = struct{}{}
1696
} else {
1697
updated[op.ChangeId] = struct{}{}
···
1775
1776
record := op.AsRecord()
1777
record.Patch = submission.Patch
1778
1779
writes = append(writes, &comatproto.RepoApplyWrites_Input_Writes_Elem{
1780
RepoApplyWrites_Update: &comatproto.RepoApplyWrites_Update{
···
2123
// the stack is identified by a UUID
2124
var stack db.Stack
2125
parentChangeId := ""
2126
for _, fp := range formatPatches {
2127
// all patches must have a jj change-id
2128
changeId, err := fp.ChangeId()
···
2153
2154
StackId: stackId,
2155
ChangeId: changeId,
2156
ParentChangeId: parentChangeId,
2157
}
2158
2159
stack = append(stack, &pull)
2160
2161
parentChangeId = changeId
2162
}
2163
2164
return stack, nil
···
29
30
"github.com/bluekeyes/go-gitdiff/gitdiff"
31
comatproto "github.com/bluesky-social/indigo/api/atproto"
32
+
"github.com/bluesky-social/indigo/atproto/syntax"
33
lexutil "github.com/bluesky-social/indigo/lex/util"
34
"github.com/go-chi/chi/v5"
35
"github.com/google/uuid"
···
1634
newStack, err := newStack(f, user, targetBranch, patch, pull.PullSource, stackId)
1635
if err != nil {
1636
log.Println("failed to create resubmitted stack", err)
1637
+
s.pages.Notice(w, "pull-resubmit-error", "Failed to merge pull request. Try again later.")
1638
return
1639
}
1640
1641
// find the diff between the stacks, first, map them by changeId
1642
origById := make(map[string]*db.Pull)
1643
newById := make(map[string]*db.Pull)
1644
+
chIdToAtUri := make(map[string]*syntax.ATURI)
1645
for _, p := range origStack {
1646
origById[p.ChangeId] = p
1647
+
1648
+
// build map from change id to existing at uris (ignore error as it shouldnt be possible here)
1649
+
pAtUri, _ := syntax.ParseATURI(fmt.Sprintf("at://%s/%s/%s", user.Did, tangled.RepoPullNSID, p.Rkey))
1650
+
chIdToAtUri[p.ChangeId] = &pAtUri
1651
}
1652
for _, p := range newStack {
1653
+
// if change id has already been given a PR use its at uri instead of the newly created (and thus incorrect)
1654
+
// one made by newStack
1655
+
if ppAt, ok := chIdToAtUri[p.ParentChangeId]; ok {
1656
+
p.ParentAt = ppAt
1657
+
}
1658
+
1659
newById[p.ChangeId] = p
1660
}
1661
···
1703
// we still need to update the hash in submission.Patch and submission.SourceRev
1704
if patchutil.Equal(newFiles, origFiles) &&
1705
origHeader.Title == newHeader.Title &&
1706
+
origHeader.Body == newHeader.Body &&
1707
+
op.ParentChangeId == np.ParentChangeId {
1708
unchanged[op.ChangeId] = struct{}{}
1709
} else {
1710
updated[op.ChangeId] = struct{}{}
···
1788
1789
record := op.AsRecord()
1790
record.Patch = submission.Patch
1791
+
record.StackInfo.Parent = (*string)(np.ParentAt)
1792
1793
writes = append(writes, &comatproto.RepoApplyWrites_Input_Writes_Elem{
1794
RepoApplyWrites_Update: &comatproto.RepoApplyWrites_Update{
···
2137
// the stack is identified by a UUID
2138
var stack db.Stack
2139
parentChangeId := ""
2140
+
var parentAt *syntax.ATURI = nil
2141
for _, fp := range formatPatches {
2142
// all patches must have a jj change-id
2143
changeId, err := fp.ChangeId()
···
2168
2169
StackId: stackId,
2170
ChangeId: changeId,
2171
+
ParentAt: parentAt,
2172
ParentChangeId: parentChangeId,
2173
}
2174
2175
stack = append(stack, &pull)
2176
2177
parentChangeId = changeId
2178
+
// this is a bit of an ugly way to create the ATURI but its the best we can do with the data flow here
2179
+
// (igore error as it shouldnt be possible here)
2180
+
parsedParentAt, _ := syntax.ParseATURI(fmt.Sprintf("at://%s/%s/%s", user.Did, tangled.RepoPullNSID, pull.Rkey));
2181
+
parentAt = &parsedParentAt
2182
}
2183
2184
return stack, nil
+1
cmd/gen.go
+1
cmd/gen.go
+21
lexicons/pulls/pull.json
+21
lexicons/pulls/pull.json
···
29
"patch": {
30
"type": "string"
31
},
32
+
"stackInfo": {
33
+
"type": "ref",
34
+
"ref": "#stackInfo"
35
+
},
36
"source": {
37
"type": "ref",
38
"ref": "#source"
···
80
"format": "at-uri"
81
}
82
}
83
+
},
84
+
"stackInfo": {
85
+
"type": "object",
86
+
"required": [
87
+
"changeId"
88
+
],
89
+
"properties": {
90
+
"changeId": {
91
+
"type": "string",
92
+
"description": "Change ID of this commit/change."
93
+
},
94
+
"parent": {
95
+
"type": "string",
96
+
"description": "AT-URI of the PR for the parent commit/change in the change stack.",
97
+
"format": "at-uri"
98
+
}
99
+
}
100
}
101
}
102
}