Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ DOCKER_BUILD_EXTRA_ARGS ?=
DOCKER_BUILDER := bufbuild-plugins
DOCKER_CACHE_DIR ?= $(TMP)/dockercache
GO ?= go
GOLANGCI_LINT_VERSION ?= v2.6.1
GOLANGCI_LINT_VERSION ?= v2.7.2
GOLANGCI_LINT := $(TMP)/golangci-lint-$(GOLANGCI_LINT_VERSION)

GO_TEST_FLAGS ?= -race -count=1
Expand Down
94 changes: 94 additions & 0 deletions internal/cmd/fetcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func postProcessCreatedPlugins(ctx context.Context, plugins []createdPlugin) err
if err := recreateNPMPackageLock(ctx, plugin); err != nil {
return fmt.Errorf("failed to recreate package-lock.json for %s: %w", newPluginRef, err)
}
if err := recreateSwiftPackageResolved(ctx, plugin); err != nil {
return fmt.Errorf("failed to resolve Swift package for %s: %w", newPluginRef, err)
}
}
if err := runPluginTests(ctx, plugins); err != nil {
return fmt.Errorf("failed to run plugin tests: %w", err)
Expand Down Expand Up @@ -119,6 +122,97 @@ func recreateNPMPackageLock(ctx context.Context, plugin createdPlugin) error {
return cmd.Run()
}

// recreateSwiftPackageResolved resolves Swift package dependencies for plugins that use Swift packages.
// It clones the git repository specified in the Dockerfile, runs 'swift package resolve',
// and moves the generated Package.resolved file to the version directory.
func recreateSwiftPackageResolved(ctx context.Context, plugin createdPlugin) error {
versionDir := filepath.Join(plugin.pluginDir, plugin.newVersion)
packageResolved := filepath.Join(versionDir, "Package.resolved")
_, err := os.Stat(packageResolved)
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return err
}
// no Package.resolved to update
return nil
}

// Read the Dockerfile to find the git clone command
dockerfile := filepath.Join(versionDir, "Dockerfile")
file, err := os.Open(dockerfile)
if err != nil {
return fmt.Errorf("failed to open Dockerfile: %w", err)
}
defer file.Close()

var gitCloneCmd string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "RUN git clone") {
// Strip the "RUN " prefix
gitCloneCmd = strings.TrimSpace(strings.TrimPrefix(line, "RUN "))
break
}
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("failed to read Dockerfile: %w", err)
}
if gitCloneCmd == "" {
return errors.New("no 'RUN git clone' command found in Dockerfile")
}

log.Printf("resolving Swift package for %s/%s:%s", plugin.org, plugin.name, plugin.newVersion)

// Execute the git clone command
cmd := exec.CommandContext(ctx, "sh", "-c", gitCloneCmd)
cmd.Dir = versionDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to run git clone: %w", err)
}

// Extract the repository name from the git clone command to determine the directory
parts := strings.Fields(gitCloneCmd)
var repoDir string
for _, part := range parts {
if strings.HasPrefix(part, "https://") {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a heuristic for the repo in the git clone line; we can loosen this over time if it doesn't work.

// Extract directory name from URL (e.g., "repo.git" or "repo")
repoName := filepath.Base(part)
repoName = strings.TrimSuffix(repoName, ".git")
repoDir = filepath.Join(versionDir, repoName)
break
}
}
if repoDir == "" {
return errors.New("failed to determine repository directory from git clone command")
}

// Run `swift package resolve` in the cloned directory
cmd = exec.CommandContext(ctx, "swift", "package", "resolve")
cmd.Dir = repoDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to run swift package resolve: %w", err)
}

// Move the Package.resolved file from the cloned directory to the version directory
src := filepath.Join(repoDir, "Package.resolved")
dest := packageResolved
if err := os.Rename(src, dest); err != nil {
return fmt.Errorf("failed to move Package.resolved: %w", err)
}

// Remove the cloned repo
if err := os.RemoveAll(repoDir); err != nil {
return fmt.Errorf("removing cloned repo: %w", err)
}

return nil
}

// runPluginTests runs 'make test PLUGINS="org/name:v<new>"' in order to generate plugin.sum files.
func runPluginTests(ctx context.Context, plugins []createdPlugin) error {
pluginsEnv := make([]string, 0, len(plugins))
Expand Down