tangled
alpha
login
or
join now
bnewbold.net
/
cobalt
13
fork
atom
go scratch code for atproto
13
fork
atom
overview
issues
pulls
pipelines
glot: rename 'compat' to 'breaking'
bnewbold.net
4 months ago
1f107a32
67114319
+24
-24
3 changed files
expand all
collapse all
unified
split
cmd
glot
README.md
compat.go
main.go
+1
-1
cmd/glot/README.md
···
89
89
If you edited an existing schema, check schema evolution rules against the published version:
90
90
91
91
```
92
92
-
glot compat
92
92
+
glot breaking
93
93
🟡 app.bsky.actor.profile
94
94
[object-required]: required fields change (main)
95
95
🟢 com.atproto.repo.strongRef
+22
-22
cmd/glot/compat.go
···
15
15
"github.com/urfave/cli/v3"
16
16
)
17
17
18
18
-
var cmdCompat = &cli.Command{
19
19
-
Name: "compat",
20
20
-
Usage: "check lexicon evolution rules",
18
18
+
var cmdBreaking = &cli.Command{
19
19
+
Name: "breaking",
20
20
+
Usage: "check for changes that break lexicon evolution rules",
21
21
ArgsUsage: `<file-or-dir>*`,
22
22
Flags: []cli.Flag{
23
23
&cli.StringFlag{
···
31
31
Usage: "output structured JSON",
32
32
},
33
33
},
34
34
-
Action: runCompat,
34
34
+
Action: runBreaking,
35
35
}
36
36
37
37
-
func runCompat(ctx context.Context, cmd *cli.Command) error {
38
38
-
return compareSchemas(ctx, cmd, compatCompare)
37
37
+
func runBreaking(ctx context.Context, cmd *cli.Command) error {
38
38
+
return compareSchemas(ctx, cmd, breakingCompare)
39
39
}
40
40
41
41
-
func compatCompare(ctx context.Context, cmd *cli.Command, nsid syntax.NSID, localJSON, remoteJSON json.RawMessage) error {
41
41
+
func breakingCompare(ctx context.Context, cmd *cli.Command, nsid syntax.NSID, localJSON, remoteJSON json.RawMessage) error {
42
42
43
43
// skip schemas which aren't in both locations
44
44
if localJSON == nil || remoteJSON == nil {
···
86
86
return err
87
87
}
88
88
89
89
-
issues := compatMaps(nsid, local.Defs, remote.Defs)
89
89
+
issues := breakingMaps(nsid, local.Defs, remote.Defs)
90
90
91
91
if cmd.Bool("json") {
92
92
for _, iss := range issues {
···
112
112
return nil
113
113
}
114
114
115
115
-
func compatMaps(nsid syntax.NSID, localMap, remoteMap map[string]lexicon.SchemaDef) []LintIssue {
115
115
+
func breakingMaps(nsid syntax.NSID, localMap, remoteMap map[string]lexicon.SchemaDef) []LintIssue {
116
116
issues := []LintIssue{}
117
117
118
118
// TODO: maybe only care about the intersection of keys, not union?
···
140
140
continue
141
141
}
142
142
143
143
-
nestIssues := compatDefs(nsid, k, local, remote)
143
143
+
nestIssues := breakingDefs(nsid, k, local, remote)
144
144
if len(nestIssues) > 0 {
145
145
issues = append(issues, nestIssues...)
146
146
}
···
149
149
return issues
150
150
}
151
151
152
152
-
func compatDefs(nsid syntax.NSID, name string, local, remote lexicon.SchemaDef) []LintIssue {
152
152
+
func breakingDefs(nsid syntax.NSID, name string, local, remote lexicon.SchemaDef) []LintIssue {
153
153
issues := []LintIssue{}
154
154
155
155
// TODO: in some situations this sort of change might actually be allowed?
···
177
177
Message: fmt.Sprintf("schema type changed (%s): %s != %s", name, l.Key, r.Key),
178
178
})
179
179
}
180
180
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: l.Record}, lexicon.SchemaDef{Inner: r.Record})...)
180
180
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: l.Record}, lexicon.SchemaDef{Inner: r.Record})...)
181
181
case lexicon.SchemaQuery:
182
182
r := remote.Inner.(lexicon.SchemaQuery)
183
183
// TODO: situation where overall parameters added/removed, and required fields involved
184
184
if l.Parameters != nil && r.Parameters != nil {
185
185
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Parameters}, lexicon.SchemaDef{Inner: *r.Parameters})...)
185
185
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Parameters}, lexicon.SchemaDef{Inner: *r.Parameters})...)
186
186
}
187
187
// TODO: situation where output requirement changes
188
188
if l.Output != nil && r.Output != nil {
189
189
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Output}, lexicon.SchemaDef{Inner: *r.Output})...)
189
189
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Output}, lexicon.SchemaDef{Inner: *r.Output})...)
190
190
}
191
191
// TODO: do Errors matter?
192
192
case lexicon.SchemaProcedure:
193
193
r := remote.Inner.(lexicon.SchemaProcedure)
194
194
// TODO: situation where overall parameters added/removed, and required fields involved
195
195
if l.Parameters != nil && r.Parameters != nil {
196
196
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Parameters}, lexicon.SchemaDef{Inner: *r.Parameters})...)
196
196
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Parameters}, lexicon.SchemaDef{Inner: *r.Parameters})...)
197
197
}
198
198
// TODO: situation where output requirement changes
199
199
if l.Input != nil && r.Input != nil {
200
200
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Input}, lexicon.SchemaDef{Inner: *r.Input})...)
200
200
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Input}, lexicon.SchemaDef{Inner: *r.Input})...)
201
201
}
202
202
// TODO: situation where output requirement changes
203
203
if l.Output != nil && r.Output != nil {
204
204
-
issues = append(issues, compatDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Output}, lexicon.SchemaDef{Inner: *r.Output})...)
204
204
+
issues = append(issues, breakingDefs(nsid, name, lexicon.SchemaDef{Inner: *l.Output}, lexicon.SchemaDef{Inner: *r.Output})...)
205
205
}
206
206
// TODO: do Errors matter?
207
207
// TODO: lexicon.SchemaSubscription (and SchemaMessage)
···
218
218
})
219
219
}
220
220
if l.Schema != nil && r.Schema != nil {
221
221
-
issues = append(issues, compatDefs(nsid, name, *l.Schema, *r.Schema)...)
221
221
+
issues = append(issues, breakingDefs(nsid, name, *l.Schema, *r.Schema)...)
222
222
}
223
223
case lexicon.SchemaNull:
224
224
// pass
···
332
332
Message: fmt.Sprintf("array min/max length change (%s)", name),
333
333
})
334
334
}
335
335
-
issues = append(issues, compatDefs(nsid, name, l.Items, r.Items)...)
335
335
+
issues = append(issues, breakingDefs(nsid, name, l.Items, r.Items)...)
336
336
case lexicon.SchemaObject:
337
337
r := remote.Inner.(lexicon.SchemaObject)
338
338
sort.Strings(l.Required)
···
357
357
Message: fmt.Sprintf("nullable fields change (%s)", name),
358
358
})
359
359
}
360
360
-
issues = append(issues, compatMaps(nsid, l.Properties, r.Properties)...)
360
360
+
issues = append(issues, breakingMaps(nsid, l.Properties, r.Properties)...)
361
361
case lexicon.SchemaBlob:
362
362
r := remote.Inner.(lexicon.SchemaBlob)
363
363
sort.Strings(l.Accept)
···
394
394
Message: fmt.Sprintf("required fields change (%s)", name),
395
395
})
396
396
}
397
397
-
issues = append(issues, compatMaps(nsid, l.Properties, r.Properties)...)
397
397
+
issues = append(issues, breakingMaps(nsid, l.Properties, r.Properties)...)
398
398
case lexicon.SchemaToken:
399
399
// pass
400
400
case lexicon.SchemaRef:
···
438
438
case lexicon.SchemaUnknown:
439
439
// pass
440
440
default:
441
441
-
slog.Warn("unhandled schema def type in compat check", "type", reflect.TypeOf(local.Inner))
441
441
+
slog.Warn("unhandled schema def type in breaking check", "type", reflect.TypeOf(local.Inner))
442
442
}
443
443
444
444
return issues
+1
-1
cmd/glot/main.go
···
34
34
cmdPull,
35
35
cmdStatus,
36
36
cmdDiff,
37
37
-
cmdCompat,
37
37
+
cmdBreaking,
38
38
cmdNew,
39
39
cmdPublish,
40
40
cmdUnpublish,