Skip to content

Commit

Permalink
Merge pull request #70 from speakeasy-api/chase/fix-11-26
Browse files Browse the repository at this point in the history
fix: add target type to codeSamples namespaces
  • Loading branch information
chase-crumbaugh authored Nov 26, 2024
2 parents fce5153 + 022d931 commit 95cb082
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 43 deletions.
58 changes: 29 additions & 29 deletions workflow/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (w Workflow) migrate(telemetryDisabled bool) Workflow {
}

codeSamplesRegistry := &SourceRegistry{
Location: codeSamplesRegistryLocation(source.Registry.Location),
Location: codeSamplesRegistryLocation(target.Target, source.Registry.Location),
}

if target.CodeSamples == nil {
Expand All @@ -179,9 +179,11 @@ func (w Workflow) migrate(telemetryDisabled bool) Workflow {
}
} else if target.CodeSamples.Registry == nil {
target.CodeSamples.Registry = codeSamplesRegistry
} else {
// Fix the registry location if it needs fixing
target.CodeSamples.Registry.Location = codeSamplesRegistryUpdatedLocation(w, target.CodeSamples)
} else if target.CodeSamples.Blocking != nil && !*target.CodeSamples.Blocking {
// Fix the registry location if it needs fixing.
// We only do this when the target is not blocking because that means we likely set it up automatically.
// We don't want to migrate a registry location that the user set up manually.
target.CodeSamples.Registry.Location = codeSamplesRegistryUpdatedLocation(target)
}

w.Targets[targetID] = target
Expand All @@ -191,9 +193,11 @@ func (w Workflow) migrate(telemetryDisabled bool) Workflow {
return w
}

// For a brief time we were not properly adding -code-samples to the namespace and so we created some duplicated registry locations
// This function checks if the registry location is a duplicate and if so, updates it to include -code-samples
func codeSamplesRegistryUpdatedLocation(wf Workflow, codeSamples *CodeSamples) SourceRegistryLocation {
// This function cleans up any issues with the codeSamples registry location.
// It trims tags/revisions, removes duplicate "-code-samples" suffixes, and adds the target type to the namespace if it's missing
func codeSamplesRegistryUpdatedLocation(target Target) SourceRegistryLocation {
codeSamples := target.CodeSamples

if codeSamples.Registry == nil {
return ""
}
Expand All @@ -203,27 +207,9 @@ func codeSamplesRegistryUpdatedLocation(wf Workflow, codeSamples *CodeSamples) S
return ""
}

// Registry namespaces should be unique
var namespaces []string
for _, source := range wf.Sources {
if source.Registry != nil {
namespaces = append(namespaces, getNamespace(source.Registry.Location))
}
}

for _, target := range wf.Targets {
if target.CodeSamples != nil && target.CodeSamples != codeSamples && target.CodeSamples.Registry != nil {
namespaces = append(namespaces, getNamespace(target.CodeSamples.Registry.Location))
}
}

// For a brief time we were not properly adding -code-samples to the namespace and so we created some duplicated registry locations
if slices.Contains(namespaces, namespace) {
namespace += "-code-samples"
}
namespace = codeSamplesNamespace(namespace, target.Target)

// Even if the namespace was already unique, we still want to return this because it also trims any tags/revisions,
// which should not be present in an output registry location
// Trims any tags/revisions, which should not be present in an output registry location
return makeRegistryLocation(namespace)
}

Expand All @@ -234,12 +220,26 @@ func getNamespace(location SourceRegistryLocation) string {
return ""
}

func codeSamplesRegistryLocation(sourceRegistryURL SourceRegistryLocation) SourceRegistryLocation {
func codeSamplesRegistryLocation(target string, sourceRegistryURL SourceRegistryLocation) SourceRegistryLocation {
registryDocument := ParseSpeakeasyRegistryReference(string(sourceRegistryURL))
newNamespace := registryDocument.NamespaceID + "-code-samples"
newNamespace := codeSamplesNamespace(registryDocument.NamespaceID, target)
return makeRegistryLocation(newNamespace)
}

func codeSamplesNamespace(namespace, target string) string {
// There was a bug where we were adding the -code-samples suffix repeatedly to the namespace if there was more than one target
for strings.HasSuffix(namespace, "-code-samples") {
namespace = strings.TrimSuffix(namespace, "-code-samples")
}

// Some people have their sources named things like "java-OAS"
if strings.Contains(namespace, target) {
return fmt.Sprintf("%s-code-samples", namespace)
} else {
return fmt.Sprintf("%s-%s-code-samples", namespace, target)
}
}

func makeRegistryLocation(namespace string) SourceRegistryLocation {
return SourceRegistryLocation(path.Join(baseRegistryURL, namespace))
}
137 changes: 123 additions & 14 deletions workflow/workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,11 @@ func TestWorkflow_Validate(t *testing.T) {

func TestMigrate_Success(t *testing.T) {
tests := []struct {
name string
in string
expected string
}{{
name: "migrates a simple workflow",
in: `workflowVersion: 1.0.0
sources:
testSource:
Expand All @@ -330,10 +332,44 @@ targets:
source: testSource
codeSamples:
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-code-samples
location: registry.speakeasyapi.dev/org/workspace/testSource-typescript-code-samples
blocking: false
`,
}, {
name: "doesn't migrate a blocking workflow with a registry location",
in: `workflowVersion: 1.0.0
sources:
testSource:
inputs:
- location: ./openapi.yaml
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource
targets:
typescript:
target: typescript
source: testSource
codeSamples:
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-custom-code-samples
`,
expected: `workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
testSource:
inputs:
- location: ./openapi.yaml
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource
targets:
typescript:
target: typescript
source: testSource
codeSamples:
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-custom-code-samples
`,
}, {
name: "migrates a workflow with a tagged registry location",
in: `workflowVersion: 1.0.0
sources:
testSource:
Expand All @@ -360,10 +396,11 @@ targets:
source: testSource
codeSamples:
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-code-samples
location: registry.speakeasyapi.dev/org/workspace/testSource-typescript-code-samples
blocking: false
`,
}, {
name: "migrates a workflow with a duplicate registry location",
in: `workflowVersion: 1.0.0
sources:
testSource:
Expand Down Expand Up @@ -394,52 +431,124 @@ targets:
source: testSource
codeSamples:
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-code-samples
location: registry.speakeasyapi.dev/org/workspace/testSource-typescript-code-samples
blocking: false
`}, {
name: "migrates a workflow with a code samples output and a source with a name that contains the target",
in: `workflowVersion: 1.0.0
sources:
testSource:
testSource-typescript:
inputs:
- location: ./openapi.yaml
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource
targets:
typescript:
target: typescript
source: testSource
source: testSource-typescript
codeSamples:
output: output.yaml
`,
expected: `workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
testSource:
testSource-typescript:
inputs:
- location: ./openapi.yaml
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource
targets:
typescript:
target: typescript
source: testSource
source: testSource-typescript
codeSamples:
output: output.yaml
registry:
location: registry.speakeasyapi.dev/org/workspace/testSource-code-samples
location: registry.speakeasyapi.dev/org/workspace/testSource-typescript-code-samples
`,
}, {
name: "migrates a workflow with multiple targets, some with multiple -code-samples suffixes",
in: `workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
Acuvity-OAS:
inputs:
- location: ./apex-openapi.yaml
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas
targets:
golang:
target: go
source: Acuvity-OAS
output: acuvity-go
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-code-samples
blocking: false
python:
target: python
source: Acuvity-OAS
output: acuvity-python
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-code-samples-code-samples
blocking: false
typescript:
target: typescript
source: Acuvity-OAS
output: acuvity-ts
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-code-samples-code-samples
blocking: false`,
expected: `workflowVersion: 1.0.0
speakeasyVersion: latest
sources:
Acuvity-OAS:
inputs:
- location: ./apex-openapi.yaml
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas
targets:
golang:
target: go
source: Acuvity-OAS
output: acuvity-go
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-go-code-samples
blocking: false
python:
target: python
source: Acuvity-OAS
output: acuvity-python
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-python-code-samples
blocking: false
typescript:
target: typescript
source: Acuvity-OAS
output: acuvity-ts
codeSamples:
registry:
location: registry.speakeasyapi.dev/acuvity-9dx/acuvity/acuvity-oas-typescript-code-samples
blocking: false
`,
}}

for _, tt := range tests {
var workflow workflow.Workflow
require.NoError(t, yaml.Unmarshal([]byte(tt.in), &workflow))
t.Run(tt.name, func(t *testing.T) {
var workflow workflow.Workflow
require.NoError(t, yaml.Unmarshal([]byte(tt.in), &workflow))

workflow = workflow.Migrate()
workflow = workflow.Migrate()

actual, err := yaml.Marshal(workflow)
require.NoError(t, err)
actual, err := yaml.Marshal(workflow)
require.NoError(t, err)

assert.Equal(t, tt.expected, string(actual))
assert.Equal(t, tt.expected, string(actual))
})
}
}

Expand Down

0 comments on commit 95cb082

Please sign in to comment.