Last active
December 22, 2024 13:10
-
-
Save pabrodez/69b3f41d24617ebafa26fdf78a0ef5c9 to your computer and use it in GitHub Desktop.
Output SpiceDb schema differences on a Azure DevOps pipeline (omitted go.mod and go.sum for brevity)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"os" | |
"strings" | |
"github.com/authzed/spicedb/pkg/development" | |
"github.com/authzed/spicedb/pkg/diff" | |
"github.com/authzed/spicedb/pkg/diff/namespace" | |
) | |
func main() { | |
if len(os.Args) != 3 { | |
log.Fatal("Usage: go run main.go <schema1> <schema2>") | |
} | |
prevSchema, currSchema := os.Args[1], os.Args[2] | |
diffedSchemas, err := compareSchemasFromStrings(prevSchema, currSchema) | |
if err != nil { | |
log.Fatalf("Error comparing schemas: %v", err) | |
} | |
changes := analyzeSchemaChanges(diffedSchemas) | |
if changes.hasChanges() { | |
printSchemaChanges(changes) | |
fmt.Printf("##vso[task.setvariable variable=hasDifferences;isOutput=true]true\n") | |
} else { | |
fmt.Println("No changes detected between the schemas.") | |
fmt.Printf("##vso[task.setvariable variable=hasDifferences;isOutput=true]false\n") | |
} | |
} | |
func compareSchemasFromStrings(schemaStr1, schemaStr2 string) (*diff.SchemaDiff, error) { | |
compiledSchema1, _, err := development.CompileSchema(schemaStr1) | |
if err != nil { | |
return nil, fmt.Errorf("error compiling schema1: %w", err) | |
} | |
compiledSchema2, _, err := development.CompileSchema(schemaStr2) | |
if err != nil { | |
return nil, fmt.Errorf("error compiling schema2: %w", err) | |
} | |
diffableSchema1 := diff.NewDiffableSchemaFromCompiledSchema(compiledSchema1) | |
diffableSchema2 := diff.NewDiffableSchemaFromCompiledSchema(compiledSchema2) | |
diffedSchemas, err := diff.DiffSchemas(diffableSchema1, diffableSchema2) | |
if err != nil { | |
return nil, fmt.Errorf("error diffing schemas: %w", err) | |
} | |
return diffedSchemas, nil | |
} | |
type schemaChanges struct { | |
addedNamespaces []string | |
removedNamespaces []string | |
changedNamespaces map[string][]namespace.Delta | |
} | |
func (sc schemaChanges) hasChanges() bool { | |
return len(sc.addedNamespaces) > 0 || len(sc.removedNamespaces) > 0 || len(sc.changedNamespaces) > 0 | |
} | |
func analyzeSchemaChanges(diffedSchemas *diff.SchemaDiff) schemaChanges { | |
changes := schemaChanges{ | |
addedNamespaces: diffedSchemas.AddedNamespaces, | |
removedNamespaces: diffedSchemas.RemovedNamespaces, | |
changedNamespaces: make(map[string][]namespace.Delta), | |
} | |
for nsName, nsDiff := range diffedSchemas.ChangedNamespaces { | |
changes.changedNamespaces[nsName] = nsDiff.Deltas() | |
} | |
return changes | |
} | |
func printSchemaChanges(changes schemaChanges) { | |
prettyPrintSchemaChanges(changes) | |
fmt.Println("\nDetailed JSON output of changed Namespaces:") | |
changedNsDeltasJSON, err := json.MarshalIndent(changes.changedNamespaces, "", " ") | |
if err != nil { | |
log.Fatalf("Error marshaling changed namespaces to JSON: %v", err) | |
} | |
fmt.Println(string(changedNsDeltasJSON)) | |
} | |
func prettyPrintSchemaChanges(changes schemaChanges) { | |
fmt.Print("Schema Changes Summary:") | |
fmt.Println(strings.Repeat("=", 30)) | |
fmt.Printf("Added Namespaces (%d):", len(changes.addedNamespaces)) | |
for _, ns := range changes.addedNamespaces { | |
fmt.Printf(" + %s\n", ns) | |
} | |
fmt.Println() | |
fmt.Printf("Removed Namespaces (%d):", len(changes.removedNamespaces)) | |
for _, ns := range changes.removedNamespaces { | |
fmt.Printf(" - %s\n", ns) | |
} | |
fmt.Println() | |
fmt.Printf("Changed Namespaces (%d):", len(changes.changedNamespaces)) | |
for nsName, deltas := range changes.changedNamespaces { | |
fmt.Printf(" * %s:\n", nsName) | |
for _, delta := range deltas { | |
actionStr := "-" | |
switch { | |
case strings.Contains(string(delta.Type), "added"): | |
actionStr = "+" | |
case strings.Contains(string(delta.Type), "removed"): | |
actionStr = "-" | |
case strings.Contains(string(delta.Type), "changed"): | |
actionStr = "~" | |
} | |
fmt.Printf(" %s %s: %s\n", actionStr, delta.Type, delta.RelationName) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trigger: none | |
jobs: | |
- job: RunComparison | |
steps: | |
- task: GoTool@0 | |
inputs: | |
version: '1.23.4' | |
- script: | | |
CURRENT_COMMIT=$(git rev-parse HEAD) | |
PREVIOUS_COMMIT=$(git rev-parse HEAD~1) | |
CURRENT_CONTENT=$(git show $CURRENT_COMMIT:./schema.zed) | |
PREVIOUS_CONTENT=$(git show $PREVIOUS_COMMIT:./schema.zed) | |
go run main.go "$PREVIOUS_CONTENT" "$CURRENT_CONTENT" | |
name: goRunDiff | |
displayName: 'Compare Schema versions' | |
- script: | | |
echo "The value of hasDifferences is: $(goRunDiff.hasDifferences)" | |
displayName: 'Print hasDifferences Variable' | |
- job: ManualValidation | |
dependsOn: RunComparison | |
pool: server | |
condition: eq(dependencies.RunComparison.outputs['goRunDiff.hasDifferences'], 'true') | |
steps: | |
- task: ManualValidation@0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment