Skip to content

Commit 69dec06

Browse files
Automate swift package resolve (#2162)
On upgrade of a Swift plugin (with a `Package.resolved` file), clone the git repo, re-run `swift package resolve`, and copy the `Package.resolved` file to the directory. Basically, an automation of the steps described in #2161. Also, bump golangci-lint to latest. Fixes #1941.
1 parent c0ac333 commit 69dec06

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ DOCKER_BUILD_EXTRA_ARGS ?=
88
DOCKER_BUILDER := bufbuild-plugins
99
DOCKER_CACHE_DIR ?= $(TMP)/dockercache
1010
GO ?= go
11-
GOLANGCI_LINT_VERSION ?= v2.6.1
11+
GOLANGCI_LINT_VERSION ?= v2.7.2
1212
GOLANGCI_LINT := $(TMP)/golangci-lint-$(GOLANGCI_LINT_VERSION)
1313

1414
GO_TEST_FLAGS ?= -race -count=1

internal/cmd/fetcher/main.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ func postProcessCreatedPlugins(ctx context.Context, plugins []createdPlugin) err
6767
if err := recreateNPMPackageLock(ctx, plugin); err != nil {
6868
return fmt.Errorf("failed to recreate package-lock.json for %s: %w", newPluginRef, err)
6969
}
70+
if err := recreateSwiftPackageResolved(ctx, plugin); err != nil {
71+
return fmt.Errorf("failed to resolve Swift package for %s: %w", newPluginRef, err)
72+
}
7073
}
7174
if err := runPluginTests(ctx, plugins); err != nil {
7275
return fmt.Errorf("failed to run plugin tests: %w", err)
@@ -119,6 +122,85 @@ func recreateNPMPackageLock(ctx context.Context, plugin createdPlugin) error {
119122
return cmd.Run()
120123
}
121124

125+
// recreateSwiftPackageResolved resolves Swift package dependencies for plugins that use Swift packages.
126+
// It clones the git repository specified in the Dockerfile, runs 'swift package resolve',
127+
// and moves the generated Package.resolved file to the version directory.
128+
func recreateSwiftPackageResolved(ctx context.Context, plugin createdPlugin) (retErr error) {
129+
versionDir := filepath.Join(plugin.pluginDir, plugin.newVersion)
130+
packageResolved := filepath.Join(versionDir, "Package.resolved")
131+
_, err := os.Stat(packageResolved)
132+
if err != nil {
133+
if !errors.Is(err, fs.ErrNotExist) {
134+
return err
135+
}
136+
// no Package.resolved to update
137+
return nil
138+
}
139+
140+
// Read the Dockerfile to find the git clone command
141+
dockerfile := filepath.Join(versionDir, "Dockerfile")
142+
file, err := os.Open(dockerfile)
143+
if err != nil {
144+
return fmt.Errorf("failed to open Dockerfile: %w", err)
145+
}
146+
defer file.Close()
147+
148+
var gitCloneCmd string
149+
scanner := bufio.NewScanner(file)
150+
for scanner.Scan() {
151+
line := scanner.Text()
152+
if strings.Contains(line, "RUN git clone") {
153+
// Strip the "RUN " prefix
154+
gitCloneCmd = strings.TrimSpace(strings.TrimPrefix(line, "RUN "))
155+
break
156+
}
157+
}
158+
if err := scanner.Err(); err != nil {
159+
return fmt.Errorf("failed to read Dockerfile: %w", err)
160+
}
161+
if gitCloneCmd == "" {
162+
return errors.New("no 'RUN git clone' command found in Dockerfile")
163+
}
164+
165+
log.Printf("resolving Swift package for %s/%s:%s", plugin.org, plugin.name, plugin.newVersion)
166+
167+
// Create a tempdir for cloning the repo
168+
tmpDir, err := os.MkdirTemp("", "swift-repo-*")
169+
if err != nil {
170+
return fmt.Errorf("creating tmp dir: %w", err)
171+
}
172+
defer func() {
173+
retErr = errors.Join(retErr, os.RemoveAll(tmpDir))
174+
}()
175+
176+
// Execute the git clone command, cloning to the tmpDir
177+
cmd := exec.CommandContext(ctx, "sh", "-c", gitCloneCmd, "--", tmpDir)
178+
cmd.Dir = versionDir
179+
cmd.Stdout = os.Stdout
180+
cmd.Stderr = os.Stderr
181+
if err := cmd.Run(); err != nil {
182+
return fmt.Errorf("failed to run git clone: %w", err)
183+
}
184+
185+
// Run `swift package resolve` in the cloned directory
186+
cmd = exec.CommandContext(ctx, "swift", "package", "resolve")
187+
cmd.Dir = tmpDir
188+
cmd.Stdout = os.Stdout
189+
cmd.Stderr = os.Stderr
190+
if err := cmd.Run(); err != nil {
191+
return fmt.Errorf("failed to run swift package resolve: %w", err)
192+
}
193+
194+
// Move the Package.resolved file from the cloned directory to the version directory
195+
src := filepath.Join(tmpDir, "Package.resolved")
196+
dest := packageResolved
197+
if err := os.Rename(src, dest); err != nil {
198+
return fmt.Errorf("failed to move Package.resolved: %w", err)
199+
}
200+
201+
return nil
202+
}
203+
122204
// runPluginTests runs 'make test PLUGINS="org/name:v<new>"' in order to generate plugin.sum files.
123205
func runPluginTests(ctx context.Context, plugins []createdPlugin) error {
124206
pluginsEnv := make([]string, 0, len(plugins))

0 commit comments

Comments
 (0)