@@ -37,12 +37,14 @@ type Command string
37
37
38
38
// The set of commands passed to the language container, in a single place to avoid typos.
39
39
const (
40
- // CommandGenerate performs generation for a configured library.
41
- CommandGenerate Command = "generate"
42
40
// CommandBuild builds a library.
43
41
CommandBuild Command = "build"
44
42
// CommandConfigure configures a new API as a library.
45
43
CommandConfigure Command = "configure"
44
+ // CommandGenerate performs generation for a configured library.
45
+ CommandGenerate Command = "generate"
46
+ // CommandReleaseInit performs release for a library.
47
+ CommandReleaseInit Command = "release-init"
46
48
)
47
49
48
50
// Docker contains all the information required to run language-specific
@@ -61,44 +63,41 @@ type Docker struct {
61
63
run func (args ... string ) error
62
64
}
63
65
64
- // GenerateRequest contains all the information required for a language
65
- // container to run the generate command.
66
- type GenerateRequest struct {
66
+ // BuildRequest contains all the information required for a language
67
+ // container to run the build command.
68
+ type BuildRequest struct {
67
69
// cfg is a pointer to the [config.Config] struct, holding general configuration
68
70
// values parsed from flags or environment variables.
69
71
Cfg * config.Config
70
72
// state is a pointer to the [config.LibrarianState] struct, representing
71
73
// the overall state of the generation and release pipeline.
72
74
State * config.LibrarianState
73
- // apiRoot specifies the root directory of the API specification repo.
74
- ApiRoot string
75
- // libraryID specifies the ID of the library to generate
75
+ // libraryID specifies the ID of the library to build.
76
76
LibraryID string
77
- // output specifies the empty output directory into which the command should
78
- // generate code
79
- Output string
80
77
// RepoDir is the local root directory of the language repository.
81
78
RepoDir string
82
79
}
83
80
84
- // BuildRequest contains all the information required for a language
85
- // container to run the build command.
86
- type BuildRequest struct {
81
+ // ConfigureRequest contains all the information required for a language
82
+ // container to run the configure command.
83
+ type ConfigureRequest struct {
87
84
// cfg is a pointer to the [config.Config] struct, holding general configuration
88
85
// values parsed from flags or environment variables.
89
86
Cfg * config.Config
90
87
// state is a pointer to the [config.LibrarianState] struct, representing
91
88
// the overall state of the generation and release pipeline.
92
89
State * config.LibrarianState
93
- // libraryID specifies the ID of the library to build
90
+ // apiRoot specifies the root directory of the API specification repo.
91
+ ApiRoot string
92
+ // libraryID specifies the ID of the library to configure.
94
93
LibraryID string
95
94
// RepoDir is the local root directory of the language repository.
96
95
RepoDir string
97
96
}
98
97
99
- // ConfigureRequest contains all the information required for a language
100
- // container to run the configure command.
101
- type ConfigureRequest struct {
98
+ // GenerateRequest contains all the information required for a language
99
+ // container to run the generate command.
100
+ type GenerateRequest struct {
102
101
// cfg is a pointer to the [config.Config] struct, holding general configuration
103
102
// values parsed from flags or environment variables.
104
103
Cfg * config.Config
@@ -107,8 +106,31 @@ type ConfigureRequest struct {
107
106
State * config.LibrarianState
108
107
// apiRoot specifies the root directory of the API specification repo.
109
108
ApiRoot string
110
- // libraryID specifies the ID of the library to generate
109
+ // libraryID specifies the ID of the library to generate.
111
110
LibraryID string
111
+ // output specifies the empty output directory into which the command should
112
+ // generate code
113
+ Output string
114
+ // RepoDir is the local root directory of the language repository.
115
+ RepoDir string
116
+ }
117
+
118
+ // ReleaseRequest contains all the information required for a language
119
+ // container to run the release command.
120
+ type ReleaseRequest struct {
121
+ // cfg is a pointer to the [config.Config] struct, holding general configuration
122
+ // values parsed from flags or environment variables.
123
+ Cfg * config.Config
124
+ // state is a pointer to the [config.LibrarianState] struct, representing
125
+ // the overall state of the generation and release pipeline.
126
+ State * config.LibrarianState
127
+ // libraryID specifies the ID of the library to release.
128
+ LibraryID string
129
+ // libraryID specifies the version of the library to release.
130
+ LibraryVersion string
131
+ // output specifies the empty output directory into which the command should
132
+ // generate code
133
+ Output string
112
134
// RepoDir is the local root directory of the language repository.
113
135
RepoDir string
114
136
}
@@ -132,7 +154,7 @@ func New(workRoot, image, uid, gid string) (*Docker, error) {
132
154
// library.
133
155
func (c * Docker ) Generate (ctx context.Context , request * GenerateRequest ) error {
134
156
jsonFilePath := filepath .Join (request .RepoDir , config .LibrarianDir , config .GenerateRequest )
135
- if err := writeRequest (request .State , request .LibraryID , jsonFilePath ); err != nil {
157
+ if err := writeLibraryState (request .State , request .LibraryID , jsonFilePath ); err != nil {
136
158
return err
137
159
}
138
160
defer func (name string ) {
@@ -165,7 +187,7 @@ func (c *Docker) Generate(ctx context.Context, request *GenerateRequest) error {
165
187
// the Librarian state file for the repository with a root of repoRoot.
166
188
func (c * Docker ) Build (ctx context.Context , request * BuildRequest ) error {
167
189
jsonFilePath := filepath .Join (request .RepoDir , config .LibrarianDir , config .BuildRequest )
168
- if err := writeRequest (request .State , request .LibraryID , jsonFilePath ); err != nil {
190
+ if err := writeLibraryState (request .State , request .LibraryID , jsonFilePath ); err != nil {
169
191
return err
170
192
}
171
193
defer func (name string ) {
@@ -194,7 +216,7 @@ func (c *Docker) Build(ctx context.Context, request *BuildRequest) error {
194
216
// Returns the configured library id if the command succeeds.
195
217
func (c * Docker ) Configure (ctx context.Context , request * ConfigureRequest ) (string , error ) {
196
218
requestFilePath := filepath .Join (request .RepoDir , config .LibrarianDir , config .ConfigureRequest )
197
- if err := writeRequest (request .State , request .LibraryID , requestFilePath ); err != nil {
219
+ if err := writeLibraryState (request .State , request .LibraryID , requestFilePath ); err != nil {
198
220
return "" , err
199
221
}
200
222
defer func () {
@@ -223,6 +245,44 @@ func (c *Docker) Configure(ctx context.Context, request *ConfigureRequest) (stri
223
245
return request .LibraryID , nil
224
246
}
225
247
248
+ // ReleaseInit initiates a release for a given language repository.
249
+ func (c * Docker ) ReleaseInit (ctx context.Context , request * ReleaseRequest ) error {
250
+ requestFilePath := filepath .Join (request .RepoDir , config .LibrarianDir , config .ReleaseInitRequest )
251
+ if err := writeLibrarianState (request .State , requestFilePath ); err != nil {
252
+ return err
253
+ }
254
+ defer func () {
255
+ err := os .Remove (requestFilePath )
256
+ if err != nil {
257
+ slog .Warn ("fail to remove file" , slog .String ("name" , requestFilePath ), slog .Any ("err" , err ))
258
+ }
259
+ }()
260
+ commandArgs := []string {
261
+ "--librarian=/librarian" ,
262
+ "--repo=/repo" ,
263
+ "--output=/output" ,
264
+ }
265
+ if request .LibraryID != "" {
266
+ commandArgs = append (commandArgs , fmt .Sprintf ("--library=%s" , request .LibraryID ))
267
+ }
268
+ if request .LibraryVersion != "" {
269
+ commandArgs = append (commandArgs , fmt .Sprintf ("--library-version=%s" , request .LibraryVersion ))
270
+ }
271
+
272
+ librarianDir := filepath .Join (request .RepoDir , config .LibrarianDir )
273
+ mounts := []string {
274
+ fmt .Sprintf ("%s:/librarian" , librarianDir ),
275
+ fmt .Sprintf ("%s:/repo:ro" , request .RepoDir ), // readonly volume
276
+ fmt .Sprintf ("%s:/output" , request .Output ),
277
+ }
278
+
279
+ if err := c .runDocker (ctx , request .Cfg , CommandReleaseInit , mounts , commandArgs ); err != nil {
280
+ return err
281
+ }
282
+
283
+ return nil
284
+ }
285
+
226
286
func (c * Docker ) runDocker (_ context.Context , cfg * config.Config , command Command , mounts []string , commandArgs []string ) (err error ) {
227
287
mounts = maybeRelocateMounts (cfg , mounts )
228
288
@@ -277,13 +337,13 @@ func (c *Docker) runCommand(cmdName string, args ...string) error {
277
337
return err
278
338
}
279
339
280
- func writeRequest (state * config.LibrarianState , libraryID , jsonFilePath string ) error {
340
+ func writeLibraryState (state * config.LibrarianState , libraryID , jsonFilePath string ) error {
281
341
if err := os .MkdirAll (filepath .Dir (jsonFilePath ), 0755 ); err != nil {
282
342
return fmt .Errorf ("failed to make directory: %w" , err )
283
343
}
284
344
jsonFile , err := os .Create (jsonFilePath )
285
345
if err != nil {
286
- return fmt .Errorf ("failed to create generate request JSON file: %w" , err )
346
+ return fmt .Errorf ("failed to create JSON file: %w" , err )
287
347
}
288
348
defer jsonFile .Close ()
289
349
@@ -304,3 +364,23 @@ func writeRequest(state *config.LibrarianState, libraryID, jsonFilePath string)
304
364
305
365
return nil
306
366
}
367
+
368
+ func writeLibrarianState (state * config.LibrarianState , jsonFilePath string ) error {
369
+ if err := os .MkdirAll (filepath .Dir (jsonFilePath ), 0755 ); err != nil {
370
+ return fmt .Errorf ("failed to make directory: %w" , err )
371
+ }
372
+ jsonFile , err := os .Create (jsonFilePath )
373
+ if err != nil {
374
+ return fmt .Errorf ("failed to create JSON file: %w" , err )
375
+ }
376
+ defer jsonFile .Close ()
377
+
378
+ data , err := json .MarshalIndent (state , "" , " " )
379
+ if err != nil {
380
+ return fmt .Errorf ("failed to marshal state to JSON: %w" , err )
381
+ }
382
+
383
+ _ , err = jsonFile .Write (data )
384
+
385
+ return err
386
+ }
0 commit comments