Skip to content

Commit 1a2aaa0

Browse files
authored
fix: only mount global files in configure command (#2377)
According to [configure container contract](https://github.com/googleapis/librarian/blob/main/doc/language-onboarding.md#configure), the `/repo` volume should only contain global files defined in global files allowlist in librarian config. Updates #1922
1 parent 72e18bc commit 1a2aaa0

File tree

6 files changed

+151
-9
lines changed

6 files changed

+151
-9
lines changed

internal/config/librarian_config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,13 @@ func (g *LibrarianConfig) LibraryConfigFor(LibraryID string) *LibraryConfig {
7474
}
7575
return nil
7676
}
77+
78+
// GetGlobalFiles returns the global files defined in the librarian config.
79+
func (g *LibrarianConfig) GetGlobalFiles() []string {
80+
var globalFiles []string
81+
for _, globalFile := range g.GlobalFilesAllowlist {
82+
globalFiles = append(globalFiles, globalFile.Path)
83+
}
84+
85+
return globalFiles
86+
}

internal/config/librarian_config_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,55 @@ func TestLibraryConfigFor(t *testing.T) {
166166
})
167167
}
168168
}
169+
170+
func TestGetGlobalFiles(t *testing.T) {
171+
for _, test := range []struct {
172+
name string
173+
config *LibrarianConfig
174+
want []string
175+
}{
176+
{
177+
name: "get_global_files",
178+
config: &LibrarianConfig{
179+
GlobalFilesAllowlist: []*GlobalFile{
180+
{
181+
Path: "a/path",
182+
Permissions: "read-only",
183+
},
184+
{
185+
Path: "another/path",
186+
Permissions: "write-only",
187+
},
188+
{
189+
Path: "other/paths",
190+
Permissions: "read-write",
191+
},
192+
},
193+
},
194+
want: []string{
195+
"a/path",
196+
"another/path",
197+
"other/paths",
198+
},
199+
},
200+
{
201+
name: "empty_global_files",
202+
config: &LibrarianConfig{
203+
GlobalFilesAllowlist: []*GlobalFile{},
204+
},
205+
want: nil,
206+
},
207+
{
208+
name: "nil_global_files",
209+
config: &LibrarianConfig{},
210+
want: nil,
211+
},
212+
} {
213+
t.Run(test.name, func(t *testing.T) {
214+
got := test.config.GetGlobalFiles()
215+
if diff := cmp.Diff(test.want, got); diff != "" {
216+
t.Errorf("GetGlobalFiles() mismatch (-want +got):\n%s", diff)
217+
}
218+
})
219+
}
220+
}

internal/docker/docker.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ type ConfigureRequest struct {
9797
// RepoDir is the local root directory of the language repository.
9898
RepoDir string
9999

100+
// GlobalFiles are global files of the language repository.
101+
GlobalFiles []string
102+
100103
// State is a pointer to the [config.LibrarianState] struct, representing
101104
// the overall state of the generation and release pipeline.
102105
State *config.LibrarianState
@@ -279,9 +282,12 @@ func (c *Docker) Configure(ctx context.Context, request *ConfigureRequest) (stri
279282
mounts := []string{
280283
fmt.Sprintf("%s:/librarian", librarianDir),
281284
fmt.Sprintf("%s:/input", generatorInput),
282-
fmt.Sprintf("%s:/repo", request.RepoDir),
283285
fmt.Sprintf("%s:/source:ro", request.ApiRoot), // readonly volume
284286
}
287+
// Mount global files as a readonly volume.
288+
for _, globalFile := range request.GlobalFiles {
289+
mounts = append(mounts, fmt.Sprintf("%s/%s:/repo/%s:ro", request.RepoDir, globalFile, globalFile))
290+
}
285291

286292
if err := c.runDocker(ctx, request.HostMount, CommandConfigure, mounts, commandArgs); err != nil {
287293
return "", err

internal/docker/docker_test.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ func TestDockerRun(t *testing.T) {
243243
LibraryID: testLibraryID,
244244
RepoDir: repoDir,
245245
ApiRoot: testAPIRoot,
246+
GlobalFiles: []string{
247+
"a/b/go.mod",
248+
"go.mod",
249+
},
246250
}
247251

248252
_, err := d.Configure(ctx, configureRequest)
@@ -253,8 +257,9 @@ func TestDockerRun(t *testing.T) {
253257
"run", "--rm",
254258
"-v", fmt.Sprintf("%s/.librarian:/librarian", repoDir),
255259
"-v", fmt.Sprintf("%s/.librarian/generator-input:/input", repoDir),
256-
"-v", fmt.Sprintf("%s:/repo", repoDir),
257260
"-v", fmt.Sprintf("%s:/source:ro", testAPIRoot),
261+
"-v", fmt.Sprintf("%s/a/b/go.mod:/repo/a/b/go.mod:ro", repoDir),
262+
"-v", fmt.Sprintf("%s/go.mod:/repo/go.mod:ro", repoDir),
258263
testImage,
259264
string(CommandConfigure),
260265
"--librarian=/librarian",
@@ -264,7 +269,38 @@ func TestDockerRun(t *testing.T) {
264269
},
265270
},
266271
{
267-
name: "Configure with multiple libraries in librarian state",
272+
name: "configure_with_nil_global_files",
273+
docker: &Docker{
274+
Image: testImage,
275+
},
276+
runCommand: func(ctx context.Context, d *Docker) error {
277+
configureRequest := &ConfigureRequest{
278+
State: state,
279+
LibraryID: testLibraryID,
280+
RepoDir: repoDir,
281+
ApiRoot: testAPIRoot,
282+
GlobalFiles: nil,
283+
}
284+
285+
_, err := d.Configure(ctx, configureRequest)
286+
287+
return err
288+
},
289+
want: []string{
290+
"run", "--rm",
291+
"-v", fmt.Sprintf("%s/.librarian:/librarian", repoDir),
292+
"-v", fmt.Sprintf("%s/.librarian/generator-input:/input", repoDir),
293+
"-v", fmt.Sprintf("%s:/source:ro", testAPIRoot),
294+
testImage,
295+
string(CommandConfigure),
296+
"--librarian=/librarian",
297+
"--input=/input",
298+
"--repo=/repo",
299+
"--source=/source",
300+
},
301+
},
302+
{
303+
name: "configure_with_multiple_libraries_in_librarian_state",
268304
docker: &Docker{
269305
Image: testImage,
270306
},
@@ -299,6 +335,10 @@ func TestDockerRun(t *testing.T) {
299335
LibraryID: testLibraryID,
300336
RepoDir: repoDir,
301337
ApiRoot: testAPIRoot,
338+
GlobalFiles: []string{
339+
"a/b/go.mod",
340+
"go.mod",
341+
},
302342
}
303343

304344
configuredLibrary, err := d.Configure(ctx, configureRequest)
@@ -312,8 +352,9 @@ func TestDockerRun(t *testing.T) {
312352
"run", "--rm",
313353
"-v", fmt.Sprintf("%s/.librarian:/librarian", repoDir),
314354
"-v", fmt.Sprintf("%s/.librarian/generator-input:/input", repoDir),
315-
"-v", fmt.Sprintf("%s:/repo", repoDir),
316355
"-v", fmt.Sprintf("%s:/source:ro", testAPIRoot),
356+
"-v", fmt.Sprintf("%s/a/b/go.mod:/repo/a/b/go.mod:ro", repoDir),
357+
"-v", fmt.Sprintf("%s/go.mod:/repo/go.mod:ro", repoDir),
317358
testImage,
318359
string(CommandConfigure),
319360
"--librarian=/librarian",

internal/librarian/generate.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,18 @@ func (r *generateRunner) runConfigureCommand(ctx context.Context) (string, error
359359
return "", err
360360
}
361361

362+
var globalFiles []string
363+
if r.librarianConfig != nil {
364+
globalFiles = r.librarianConfig.GetGlobalFiles()
365+
}
366+
362367
configureRequest := &docker.ConfigureRequest{
363-
ApiRoot: apiRoot,
364-
HostMount: r.hostMount,
365-
LibraryID: r.library,
366-
RepoDir: r.repo.GetDir(),
367-
State: r.state,
368+
ApiRoot: apiRoot,
369+
HostMount: r.hostMount,
370+
LibraryID: r.library,
371+
RepoDir: r.repo.GetDir(),
372+
GlobalFiles: globalFiles,
373+
State: r.state,
368374
}
369375
slog.Info("Performing configuration for library", "id", r.library)
370376
if _, err := r.containerClient.Configure(ctx, configureRequest); err != nil {

internal/librarian/generate_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,33 @@ func TestGenerateScenarios(t *testing.T) {
629629
wantBuildCalls: 1,
630630
wantConfigureCalls: 1,
631631
},
632+
{
633+
name: "generate_single_library_with_librarian_config",
634+
api: "some/api",
635+
library: "some-library",
636+
state: &config.LibrarianState{
637+
Image: "gcr.io/test/image:v1.2.3",
638+
},
639+
container: &mockContainerClient{
640+
wantLibraryGen: true,
641+
configureLibraryPaths: []string{
642+
"src/a",
643+
},
644+
},
645+
librarianConfig: &config.LibrarianConfig{
646+
GlobalFilesAllowlist: []*config.GlobalFile{
647+
{
648+
Path: "a/path/example.txt",
649+
Permissions: "read-only",
650+
},
651+
},
652+
},
653+
ghClient: &mockGitHubClient{},
654+
build: true,
655+
wantGenerateCalls: 1,
656+
wantBuildCalls: 1,
657+
wantConfigureCalls: 1,
658+
},
632659
{
633660
name: "generate single existing library by library id",
634661
library: "some-library",

0 commit comments

Comments
 (0)