Skip to content

Commit e4c20cb

Browse files
committed
cleanup and fix tests
1 parent 15125a4 commit e4c20cb

File tree

4 files changed

+106
-64
lines changed

4 files changed

+106
-64
lines changed

cmd/customcode.go

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,6 @@ var registerCustomCodeCmd = &model.ExecutableCommand[RegisterCustomCodeFlags]{
4848
Shorthand: "a",
4949
Description: "apply existing custom code patches without running generation",
5050
},
51-
flag.BooleanFlag{
52-
Name: "latest-hash",
53-
Description: "show the latest commit hash from gen.lock that contains custom code changes",
54-
},
55-
flag.StringFlag{
56-
Name: "installationURL",
57-
Shorthand: "i",
58-
Description: "the language specific installation URL for installation instructions if the SDK is not published to a package manager",
59-
},
60-
flag.MapFlag{
61-
Name: "installationURLs",
62-
Description: "a map from target ID to installation URL for installation instructions if the SDK is not published to a package manager",
63-
},
64-
flag.StringFlag{
65-
Name: "repo",
66-
Shorthand: "r",
67-
Description: "the repository URL for the SDK, if the published (-p) flag isn't used this will be used to generate installation instructions",
68-
},
6951
flag.EnumFlag{
7052
Name: "output",
7153
Shorthand: "o",
@@ -104,18 +86,12 @@ func registerCustomCode(ctx context.Context, flags RegisterCustomCodeFlags) erro
10486
if err != nil {
10587
return fmt.Errorf("Could not find workflow file")
10688
}
107-
for targetName, target := range wf.Targets {
108-
fmt.Println("Applying target ", targetName)
89+
for _, target := range wf.Targets {
10990
registercustomcode.ApplyCustomCodePatch(ctx, target)
11091
}
11192
return nil
11293
}
11394

114-
// If --latest-hash flag is provided, show the commit hash from gen.lock
115-
if flags.LatestHash {
116-
return registercustomcode.ShowLatestCommitHash(ctx)
117-
}
118-
11995
// Call the registercustomcode functionality
12096
return registercustomcode.RegisterCustomCode(ctx, func(targetName string) error {
12197
opts := []run.Opt{

integration/customcode_multitarget_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestMultiTargetCustomCode(t *testing.T) {
3232
testMultiTargetIncrementalCustomCode(t, speakeasyBinary)
3333
})
3434

35-
t.Run("ConflictResolutionAcceptOurs", func(t *testing.T) {
35+
t.Run("ConflictResolutionAcceptOurs1", func(t *testing.T) {
3636
t.Parallel()
3737
testMultiTargetCustomCodeConflictResolutionAcceptOurs(t, speakeasyBinary)
3838
})
@@ -296,7 +296,7 @@ func testMultiTargetCustomCodeConflictResolutionAcceptOurs(t *testing.T, speakea
296296

297297
// Step 1: Add custom code to ALL targets
298298
modifyLineInFileByPrefix(t, goFilePath, "// The name that needs to be", "\t// custom code in go target")
299-
modifyLineInFileByPrefix(t, tsFilePath, "* @deprecated This namespace", "// custom code in typescript target")
299+
modifyLineInFileByPrefix(t, tsFilePath, "* @internal", "// custom code in typescript target")
300300

301301
// Step 2: Register custom code for all targets
302302
customCodeCmd := exec.Command(speakeasyBinary, "customcode", "--output", "console")
@@ -593,7 +593,7 @@ func testMultiTargetCustomCodeConflictResolutionAcceptTheirs(t *testing.T, speak
593593

594594
// Step 1: Add custom code to ALL targets
595595
modifyLineInFileByPrefix(t, goFilePath, "// The name that needs to be", "\t// custom code in go target")
596-
modifyLineInFileByPrefix(t, tsFilePath, "* @deprecated This namespace", "// custom code in typescript target")
596+
modifyLineInFileByPrefix(t, tsFilePath, "* @internal", "// custom code in typescript target")
597597

598598
// Step 2: Register custom code for all targets
599599
customCodeCmd := exec.Command(speakeasyBinary, "customcode", "--output", "console")

integration/customcode_singletarget_test.go

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -595,38 +595,52 @@ func ValidateUserID(id int64) bool {
595595
gitAddOutput, gitAddErr := gitAddCmd.CombinedOutput()
596596
require.NoError(t, gitAddErr, "git add should succeed: %s", string(gitAddOutput))
597597

598-
// Register custom code
598+
// Try to register custom code with new file - should fail
599599
customCodeCmd := exec.Command(speakeasyBinary, "customcode", "--output", "console")
600600
customCodeCmd.Dir = temp
601601
customCodeOutput, customCodeErr := customCodeCmd.CombinedOutput()
602-
require.NoError(t, customCodeErr, "customcode command should succeed: %s", string(customCodeOutput))
602+
require.Error(t, customCodeErr, "customcode command should fail with new file: %s", string(customCodeOutput))
603+
require.Contains(t, string(customCodeOutput), "Cannot register new files through customcode", "Error should mention new files not supported")
603604

604-
// Verify patch file was created
605+
// Commit the new file to make it part of the codebase
606+
gitCommitCmd := exec.Command("git", "commit", "-m", "Add helper file")
607+
gitCommitCmd.Dir = temp
608+
_, err = gitCommitCmd.CombinedOutput()
609+
require.NoError(t, err, "git commit should succeed")
610+
611+
// Now make a modification to an existing file to test normal customcode flow
612+
getUserByNamePath := filepath.Join(temp, "models", "operations", "getuserbyname.go")
613+
registerCustomCodeByPrefix(t, speakeasyBinary, temp, getUserByNamePath, "// The name that needs to be fetched", "\t// custom code in existing file")
614+
615+
// Verify patch file was created for the modification
605616
patchFile := filepath.Join(temp, ".speakeasy", "patches", "custom-code.diff")
606617
_, err = os.Stat(patchFile)
607-
require.NoError(t, err, "patch file should exist at %s", patchFile)
618+
require.NoError(t, err, "patch file should exist for file modifications")
608619

609620
// Verify the file exists after registration (before regeneration)
610621
_, err = os.Stat(helperFilePath)
611622
require.NoError(t, err, "Helper file should exist after registration")
612623

613624
// Run speakeasy run to regenerate the SDK
614-
// This should apply the patch and preserve the new file
625+
// This should apply the patch for the existing file modification and preserve the committed helper file
615626
runRegeneration(t, speakeasyBinary, temp, true)
616627

617-
// Verify the new file still exists after regeneration
628+
// Verify the helper file still exists after regeneration (it was committed, so should be preserved)
618629
_, err = os.Stat(helperFilePath)
619630
require.NoError(t, err, "Helper file should exist after regeneration")
620631

621-
// Verify the file contents are preserved exactly
632+
// Verify the helper file contents are preserved exactly
622633
verifyCustomCodePresent(t, helperFilePath, "FormatUserID")
623634
verifyCustomCodePresent(t, helperFilePath, "ValidateUserID")
624635
verifyCustomCodePresent(t, helperFilePath, "package utils")
625636

626-
// Read the entire file and verify exact content match
637+
// Read the entire helper file and verify exact content match
627638
actualContent, err := os.ReadFile(helperFilePath)
628639
require.NoError(t, err, "Failed to read helper file after regeneration")
629640
require.Equal(t, helperFileContent, string(actualContent), "Helper file content should be preserved exactly")
641+
642+
// Verify the custom code modification was applied to the existing file
643+
verifyCustomCodePresent(t, getUserByNamePath, "// custom code in existing file")
630644
}
631645

632646
// testCustomCodeNewFileDeletion tests that deleting a custom file is properly registered and persisted
@@ -659,44 +673,38 @@ func FormatUserID(id int64) string {
659673
_, err = gitAddCmd.CombinedOutput()
660674
require.NoError(t, err, "git add should succeed")
661675

662-
// Register custom code (registers the new file)
663-
customCodeCmd := exec.Command(speakeasyBinary, "customcode", "--output", "console")
664-
customCodeCmd.Dir = temp
665-
customCodeOutput, customCodeErr := customCodeCmd.CombinedOutput()
666-
require.NoError(t, customCodeErr, "customcode command should succeed: %s", string(customCodeOutput))
667-
668-
// Verify patch file was created
669-
patchFile := filepath.Join(temp, ".speakeasy", "patches", "custom-code.diff")
670-
_, err = os.Stat(patchFile)
671-
require.NoError(t, err, "patch file should exist after registering new file")
672-
673-
// Regenerate and verify the file is preserved
674-
runRegeneration(t, speakeasyBinary, temp, true)
675-
_, err = os.Stat(helperFilePath)
676-
require.NoError(t, err, "Helper file should exist after first regeneration")
677-
678-
// Commit the regeneration so the file becomes part of HEAD
679-
gitCommitCmd := exec.Command("git", "commit", "-am", "regeneration with custom file")
676+
// Commit the new file to make it part of the codebase
677+
gitCommitCmd := exec.Command("git", "commit", "-m", "Add helper file")
680678
gitCommitCmd.Dir = temp
681679
_, err = gitCommitCmd.CombinedOutput()
682-
require.NoError(t, err, "git commit should succeed after regeneration")
680+
require.NoError(t, err, "git commit should succeed")
683681

684682
// Now delete the file
685683
err = os.Remove(helperFilePath)
686684
require.NoError(t, err, "Failed to delete helper file")
687685

688-
// Register the deletion
689-
customCodeCmd = exec.Command(speakeasyBinary, "customcode", "--output", "console")
690-
customCodeCmd.Dir = temp
691-
customCodeOutput, customCodeErr = customCodeCmd.CombinedOutput()
692-
require.NoError(t, customCodeErr, "customcode command should succeed after deletion: %s", string(customCodeOutput))
686+
// Commit the deletion
687+
gitCommitDeleteCmd := exec.Command("git", "commit", "-am", "Delete helper file")
688+
gitCommitDeleteCmd.Dir = temp
689+
_, err = gitCommitDeleteCmd.CombinedOutput()
690+
require.NoError(t, err, "git commit for deletion should succeed")
691+
692+
// Now make a modification to an existing file to test normal customcode flow
693+
getUserByNamePath := filepath.Join(temp, "models", "operations", "getuserbyname.go")
694+
registerCustomCodeByPrefix(t, speakeasyBinary, temp, getUserByNamePath, "// The name that needs to be fetched", "\t// custom code for deletion test")
693695

694-
// Verify patch file was removed (no custom code remaining)
696+
// Verify patch file was created for the modification
697+
patchFile := filepath.Join(temp, ".speakeasy", "patches", "custom-code.diff")
695698
_, err = os.Stat(patchFile)
696-
require.True(t, os.IsNotExist(err), "patch file should not exist after deleting the only custom file")
699+
require.NoError(t, err, "patch file should exist for file modifications")
697700

698-
// Regenerate and verify the file remains deleted
701+
// Run regeneration to test that the custom code is preserved and deleted file stays deleted
699702
runRegeneration(t, speakeasyBinary, temp, true)
703+
704+
// Verify the helper file does NOT exist after regeneration (it was deleted and committed)
700705
_, err = os.Stat(helperFilePath)
701-
require.True(t, os.IsNotExist(err), "Helper file should not exist after regeneration with deletion registered")
706+
require.True(t, os.IsNotExist(err), "Helper file should not exist after regeneration (was deleted)")
707+
708+
// Verify the custom code modification was applied to the existing file
709+
verifyCustomCodePresent(t, getUserByNamePath, "// custom code for deletion test")
702710
}

internal/registercustomcode/registercustomcode.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,11 @@ func isLocalPath(location workflow.LocationString) bool {
675675

676676
// Git operations
677677
func captureCustomCodeDiff(outDir string, excludePaths []string) (string, error) {
678+
// First, check for new files and deletions in the staged changes
679+
if err := checkForNewFilesOrDeletions(outDir); err != nil {
680+
return "", err
681+
}
682+
678683
args := []string{"diff", "HEAD", outDir}
679684

680685
// Filter excludePaths to only include children of outDir
@@ -699,6 +704,59 @@ func captureCustomCodeDiff(outDir string, excludePaths []string) (string, error)
699704
return string(combinedOutput), nil
700705
}
701706

707+
// checkForNewFilesOrDeletions checks if there are any new files or file deletions
708+
// in the staged changes and returns an error if found, as these are not supported
709+
func checkForNewFilesOrDeletions(outDir string) error {
710+
// Check for new files (A) and deletions (D) using git diff with filter
711+
cmd := exec.Command("git", "diff", "--name-status", "--diff-filter=AD", "HEAD", outDir)
712+
output, err := cmd.Output()
713+
if err != nil {
714+
return fmt.Errorf("failed to check for new files or deletions: %w", err)
715+
}
716+
717+
outputStr := strings.TrimSpace(string(output))
718+
if outputStr == "" {
719+
// No additions or deletions found
720+
return nil
721+
}
722+
723+
lines := strings.Split(outputStr, "\n")
724+
var newFiles []string
725+
var deletedFiles []string
726+
727+
for _, line := range lines {
728+
if line == "" {
729+
continue
730+
}
731+
732+
// Format is "STATUS\tFILENAME"
733+
parts := strings.SplitN(line, "\t", 2)
734+
if len(parts) != 2 {
735+
continue
736+
}
737+
738+
status := parts[0]
739+
filename := parts[1]
740+
741+
if status == "A" {
742+
newFiles = append(newFiles, filename)
743+
} else if status == "D" {
744+
deletedFiles = append(deletedFiles, filename)
745+
}
746+
}
747+
748+
// Return error if we found new files or deletions
749+
if len(newFiles) > 0 {
750+
return fmt.Errorf("Cannot register new files through customcode. New files found: %s", strings.Join(newFiles, ", "))
751+
}
752+
753+
if len(deletedFiles) > 0 {
754+
return fmt.Errorf("Cannot register file deletions through customcode. Deleted files found: %s", strings.Join(deletedFiles, ", "))
755+
}
756+
757+
return nil
758+
}
759+
702760
func checkForChangesWithExclusions(dir string, excludePaths []string) (bool, error) {
703761
args := []string{"diff", "--cached", dir}
704762

0 commit comments

Comments
 (0)